authorgravatar for 14938807+xackus@users.noreply.github.comxackus <14938807+xackus@users.noreply.github.com> 2021-03-30 18:28:50+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-12 11:55:39+03:00
logb5c117d0516d13019fc79b80bc6be1aa31d51d85
treef6a0a00b36397e7db34405d7507a24afcda6c5a9
parent986a71234bf2b40284117cac0537e68071b29b33

translate-c: fix enums that require c_uint type


3 files changed, 186 insertions(+), 152 deletions(-)

src/translate_c.zig+2-4
...@@ -1117,9 +1117,7 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E...@@ -1117,9 +1117,7 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E
1117 // default to the usual integer type used for all the enums.1117 // default to the usual integer type used for all the enums.
11181118
1119 // default to c_int since msvc and gcc default to different types1119 // default to c_int since msvc and gcc default to different types
1120 const init_arg_expr = if (int_type.ptr != null and1120 const init_arg_expr = if (int_type.ptr != null)
1121 !isCBuiltinType(int_type, .UInt) and
1122 !isCBuiltinType(int_type, .Int))
1123 transQualType(c, scope, int_type, enum_loc) catch |err| switch (err) {1121 transQualType(c, scope, int_type, enum_loc) catch |err| switch (err) {
1124 error.UnsupportedType => {1122 error.UnsupportedType => {
1125 return failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});1123 return failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
...@@ -2285,8 +2283,8 @@ fn transCCast(...@@ -2285,8 +2283,8 @@ fn transCCast(
2285 // 1. If src_type is an enum, determine the underlying signed int type2283 // 1. If src_type is an enum, determine the underlying signed int type
2286 // 2. Extend or truncate without changing signed-ness.2284 // 2. Extend or truncate without changing signed-ness.
2287 // 3. Bit-cast to correct signed-ness2285 // 3. Bit-cast to correct signed-ness
2288 const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type);
2289 const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);2286 const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);
2287 const src_type_is_signed = cIsSignedInteger(src_int_type);
2290 var src_int_expr = if (cIsInteger(src_type)) expr else try Tag.enum_to_int.create(c.arena, expr);2288 var src_int_expr = if (cIsInteger(src_type)) expr else try Tag.enum_to_int.create(c.arena, expr);
22912289
2292 if (isBoolRes(src_int_expr)) {2290 if (isBoolRes(src_int_expr)) {
test/run_translated_c.zig+10
...@@ -1540,4 +1540,14 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -1540,4 +1540,14 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
1540 \\ return 0;1540 \\ return 0;
1541 \\}1541 \\}
1542 , "");1542 , "");
1543
1544 cases.add("enum with value that fits in c_uint but not c_int, issue #8003",
1545 \\#include <stdlib.h>
1546 \\enum my_enum {
1547 \\ FORCE_UINT = 0xffffffff
1548 \\};
1549 \\int main(void) {
1550 \\ if(FORCE_UINT != 0xffffffff) abort();
1551 \\}
1552 , "");
1543}1553}
test/translate_c.zig+174-148
...@@ -3,6 +3,8 @@ const std = @import("std");...@@ -3,6 +3,8 @@ const std = @import("std");
3const CrossTarget = std.zig.CrossTarget;3const CrossTarget = std.zig.CrossTarget;
44
5pub fn addCases(cases: *tests.TranslateCContext) void {5pub fn addCases(cases: *tests.TranslateCContext) void {
6 const default_enum_type = if (std.Target.current.abi == .msvc) "c_int" else "c_uint";
7
6 cases.add("field access is grouped if necessary",8 cases.add("field access is grouped if necessary",
7 \\unsigned long foo(unsigned long x) {9 \\unsigned long foo(unsigned long x) {
8 \\ return ((union{unsigned long _x}){x})._x;10 \\ return ((union{unsigned long _x}){x})._x;
...@@ -28,17 +30,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -28,17 +30,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
28 \\ int a, b;30 \\ int a, b;
29 \\} Bar;31 \\} Bar;
30 , &[_][]const u8{32 , &[_][]const u8{
31 \\pub const Foo = extern enum(c_int) {33 \\pub const Foo = extern enum(
32 \\ A,34 ++ default_enum_type ++
33 \\ B,35 \\) {
34 \\ _,36 \\ A,
35 \\};37 \\ B,
36 \\pub const FooA = @enumToInt(Foo.A);38 \\ _,
37 \\pub const FooB = @enumToInt(Foo.B);39 \\};
38 \\pub const Bar = extern struct {40 \\pub const FooA = @enumToInt(Foo.A);
39 \\ a: c_int,41 \\pub const FooB = @enumToInt(Foo.B);
40 \\ b: c_int,42 \\pub const Bar = extern struct {
41 \\};43 \\ a: c_int,
44 \\ b: c_int,
45 \\};
42 });46 });
4347
44 cases.add("if as while stmt has semicolon",48 cases.add("if as while stmt has semicolon",
...@@ -118,29 +122,33 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -118,29 +122,33 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
118 \\}122 \\}
119 , &[_][]const u8{123 , &[_][]const u8{
120 \\pub export fn foo() void {124 \\pub export fn foo() void {
121 \\ const enum_Foo = extern enum(c_int) {125 \\ const enum_Foo = extern enum(
122 \\ A,126 ++ default_enum_type ++
123 \\ B,127 \\) {
124 \\ C,128 \\ A,
125 \\ _,129 \\ B,
126 \\ };130 \\ C,
127 \\ const A = @enumToInt(enum_Foo.A);131 \\ _,
128 \\ const B = @enumToInt(enum_Foo.B);132 \\ };
129 \\ const C = @enumToInt(enum_Foo.C);133 \\ const A = @enumToInt(enum_Foo.A);
130 \\ var a: enum_Foo = @import("std").meta.cast(enum_Foo, B);134 \\ const B = @enumToInt(enum_Foo.B);
131 \\ {135 \\ const C = @enumToInt(enum_Foo.C);
132 \\ const enum_Foo = extern enum(c_int) {136 \\ var a: enum_Foo = @import("std").meta.cast(enum_Foo, B);
133 \\ A,137 \\ {
134 \\ B,138 \\ const enum_Foo = extern enum(
135 \\ C,139 ++ default_enum_type ++
136 \\ _,140 \\) {
137 \\ };141 \\ A,
138 \\ const A_2 = @enumToInt(enum_Foo.A);142 \\ B,
139 \\ const B_3 = @enumToInt(enum_Foo.B);143 \\ C,
140 \\ const C_4 = @enumToInt(enum_Foo.C);144 \\ _,
141 \\ var a_5: enum_Foo = @import("std").meta.cast(enum_Foo, B_3);145 \\ };
142 \\ }146 \\ const A_2 = @enumToInt(enum_Foo.A);
143 \\}147 \\ const B_3 = @enumToInt(enum_Foo.B);
148 \\ const C_4 = @enumToInt(enum_Foo.C);
149 \\ var a_5: enum_Foo = @import("std").meta.cast(enum_Foo, B_3);
150 \\ }
151 \\}
144 });152 });
145153
146 cases.add("scoped record",154 cases.add("scoped record",
...@@ -1702,47 +1710,55 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1702,47 +1710,55 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1702 \\ p,1710 \\ p,
1703 \\};1711 \\};
1704 , &[_][]const u8{1712 , &[_][]const u8{
1705 \\pub const d = extern enum(c_int) {1713 \\pub const d = extern enum(
1706 \\ a,1714 ++ default_enum_type ++
1707 \\ b,1715 \\) {
1708 \\ c,1716 \\ a,
1709 \\ _,1717 \\ b,
1710 \\};1718 \\ c,
1711 \\pub const a = @enumToInt(d.a);1719 \\ _,
1712 \\pub const b = @enumToInt(d.b);1720 \\};
1713 \\pub const c = @enumToInt(d.c);1721 \\pub const a = @enumToInt(d.a);
1714 \\const enum_unnamed_1 = extern enum(c_int) {1722 \\pub const b = @enumToInt(d.b);
1715 \\ e = 0,1723 \\pub const c = @enumToInt(d.c);
1716 \\ f = 4,1724 \\const enum_unnamed_1 = extern enum(
1717 \\ g = 5,1725 ++ default_enum_type ++
1718 \\ _,1726 \\) {
1719 \\};1727 \\ e = 0,
1720 \\pub const e = @enumToInt(enum_unnamed_1.e);1728 \\ f = 4,
1721 \\pub const f = @enumToInt(enum_unnamed_1.f);1729 \\ g = 5,
1722 \\pub const g = @enumToInt(enum_unnamed_1.g);1730 \\ _,
1723 \\pub export var h: enum_unnamed_1 = @import("std").meta.cast(enum_unnamed_1, e);1731 \\};
1724 \\const enum_unnamed_2 = extern enum(c_int) {1732 \\pub const e = @enumToInt(enum_unnamed_1.e);
1725 \\ i,1733 \\pub const f = @enumToInt(enum_unnamed_1.f);
1726 \\ j,1734 \\pub const g = @enumToInt(enum_unnamed_1.g);
1727 \\ k,1735 \\pub export var h: enum_unnamed_1 = @import("std").meta.cast(enum_unnamed_1, e);
1728 \\ _,1736 \\const enum_unnamed_2 = extern enum(
1729 \\};1737 ++ default_enum_type ++
1730 \\pub const i = @enumToInt(enum_unnamed_2.i);1738 \\) {
1731 \\pub const j = @enumToInt(enum_unnamed_2.j);1739 \\ i,
1732 \\pub const k = @enumToInt(enum_unnamed_2.k);1740 \\ j,
1733 \\pub const struct_Baz = extern struct {1741 \\ k,
1734 \\ l: enum_unnamed_2,1742 \\ _,
1735 \\ m: d,1743 \\};
1736 \\};1744 \\pub const i = @enumToInt(enum_unnamed_2.i);
1737 \\pub const enum_i = extern enum(c_int) {1745 \\pub const j = @enumToInt(enum_unnamed_2.j);
1738 \\ n,1746 \\pub const k = @enumToInt(enum_unnamed_2.k);
1739 \\ o,1747 \\pub const struct_Baz = extern struct {
1740 \\ p,1748 \\ l: enum_unnamed_2,
1741 \\ _,1749 \\ m: d,
1742 \\};1750 \\};
1743 \\pub const n = @enumToInt(enum_i.n);1751 \\pub const enum_i = extern enum(
1744 \\pub const o = @enumToInt(enum_i.o);1752 ++ default_enum_type ++
1745 \\pub const p = @enumToInt(enum_i.p);1753 \\) {
1754 \\ n,
1755 \\ o,
1756 \\ p,
1757 \\ _,
1758 \\};
1759 \\pub const n = @enumToInt(enum_i.n);
1760 \\pub const o = @enumToInt(enum_i.o);
1761 \\pub const p = @enumToInt(enum_i.p);
1746 ,1762 ,
1747 \\pub const Baz = struct_Baz;1763 \\pub const Baz = struct_Baz;
1748 });1764 });
...@@ -2234,13 +2250,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2234,13 +2250,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2234 \\ Two,2250 \\ Two,
2235 \\};2251 \\};
2236 , &[_][]const u8{2252 , &[_][]const u8{
2237 \\const enum_unnamed_1 = extern enum(c_int) {2253 \\const enum_unnamed_1 = extern enum(
2238 \\ One,2254 ++ default_enum_type ++
2239 \\ Two,2255 \\) {
2240 \\ _,2256 \\ One,
2241 \\};2257 \\ Two,
2242 \\pub const One = @enumToInt(enum_unnamed_1.One);2258 \\ _,
2243 \\pub const Two = @enumToInt(enum_unnamed_1.Two);2259 \\};
2260 \\pub const One = @enumToInt(enum_unnamed_1.One);
2261 \\pub const Two = @enumToInt(enum_unnamed_1.Two);
2244 });2262 });
22452263
2246 cases.add("c style cast",2264 cases.add("c style cast",
...@@ -2338,35 +2356,37 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2338,35 +2356,37 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2338 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);2356 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
2339 \\}2357 \\}
2340 , &[_][]const u8{2358 , &[_][]const u8{
2341 \\pub const enum_Foo = extern enum(c_int) {2359 \\pub const enum_Foo = extern enum(
2342 \\ A,2360 ++ default_enum_type ++
2343 \\ B,2361 \\) {
2344 \\ C,2362 \\ A,
2345 \\ _,2363 \\ B,
2346 \\};2364 \\ C,
2347 \\pub const FooA = @enumToInt(enum_Foo.A);2365 \\ _,
2348 \\pub const FooB = @enumToInt(enum_Foo.B);2366 \\};
2349 \\pub const FooC = @enumToInt(enum_Foo.C);2367 \\pub const FooA = @enumToInt(enum_Foo.A);
2350 \\pub const SomeTypedef = c_int;2368 \\pub const FooB = @enumToInt(enum_Foo.B);
2351 \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {2369 \\pub const FooC = @enumToInt(enum_Foo.C);
2352 \\ var a = arg_a;2370 \\pub const SomeTypedef = c_int;
2353 \\ var b = arg_b;2371 \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
2354 \\ var c = arg_c;2372 \\ var a = arg_a;
2355 \\ var d: enum_Foo = @import("std").meta.cast(enum_Foo, FooA);2373 \\ var b = arg_b;
2356 \\ var e: c_int = @boolToInt((a != 0) and (b != 0));2374 \\ var c = arg_c;
2357 \\ var f: c_int = @boolToInt((b != 0) and (c != null));2375 \\ var d: enum_Foo = @import("std").meta.cast(enum_Foo, FooA);
2358 \\ var g: c_int = @boolToInt((a != 0) and (c != null));2376 \\ var e: c_int = @boolToInt((a != 0) and (b != 0));
2359 \\ var h: c_int = @boolToInt((a != 0) or (b != 0));2377 \\ var f: c_int = @boolToInt((b != 0) and (c != null));
2360 \\ var i: c_int = @boolToInt((b != 0) or (c != null));2378 \\ var g: c_int = @boolToInt((a != 0) and (c != null));
2361 \\ var j: c_int = @boolToInt((a != 0) or (c != null));2379 \\ var h: c_int = @boolToInt((a != 0) or (b != 0));
2362 \\ var k: c_int = @boolToInt((a != 0) or (@bitCast(c_int, @enumToInt(d)) != 0));2380 \\ var i: c_int = @boolToInt((b != 0) or (c != null));
2363 \\ var l: c_int = @boolToInt((@bitCast(c_int, @enumToInt(d)) != 0) and (b != 0));2381 \\ var j: c_int = @boolToInt((a != 0) or (c != null));
2364 \\ var m: c_int = @boolToInt((c != null) or (@bitCast(c_uint, @enumToInt(d)) != 0));2382 \\ var k: c_int = @boolToInt((a != 0) or (@bitCast(c_int, @enumToInt(d)) != 0));
2365 \\ var td: SomeTypedef = 44;2383 \\ var l: c_int = @boolToInt((@bitCast(c_int, @enumToInt(d)) != 0) and (b != 0));
2366 \\ var o: c_int = @boolToInt((td != 0) or (b != 0));2384 \\ var m: c_int = @boolToInt((c != null) or (@bitCast(c_uint, @enumToInt(d)) != 0));
2367 \\ var p: c_int = @boolToInt((c != null) and (td != 0));2385 \\ var td: SomeTypedef = 44;
2368 \\ return (((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p;2386 \\ var o: c_int = @boolToInt((td != 0) or (b != 0));
2369 \\}2387 \\ var p: c_int = @boolToInt((c != null) and (td != 0));
2388 \\ return (((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p;
2389 \\}
2370 ,2390 ,
2371 \\pub const Foo = enum_Foo;2391 \\pub const Foo = enum_Foo;
2372 });2392 });
...@@ -2387,14 +2407,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2387,14 +2407,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2387 \\ y: c_int,2407 \\ y: c_int,
2388 \\};2408 \\};
2389 ,2409 ,
2390 \\pub const enum_Bar = extern enum(c_int) {2410 \\pub const enum_Bar = extern enum(
2391 \\ A,2411 ++ default_enum_type ++
2392 \\ B,2412 \\) {
2393 \\ _,2413 \\ A,
2394 \\};2414 \\ B,
2395 \\pub const BarA = @enumToInt(enum_Bar.A);2415 \\ _,
2396 \\pub const BarB = @enumToInt(enum_Bar.B);2416 \\};
2397 \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;2417 \\pub const BarA = @enumToInt(enum_Bar.A);
2418 \\pub const BarB = @enumToInt(enum_Bar.B);
2419 \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
2398 ,2420 ,
2399 \\pub const Foo = struct_Foo;2421 \\pub const Foo = struct_Foo;
2400 \\pub const Bar = enum_Bar;2422 \\pub const Bar = enum_Bar;
...@@ -2664,26 +2686,28 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2664,26 +2686,28 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2664 \\ return 4;2686 \\ return 4;
2665 \\}2687 \\}
2666 , &[_][]const u8{2688 , &[_][]const u8{
2667 \\pub const enum_SomeEnum = extern enum(c_int) {2689 \\pub const enum_SomeEnum = extern enum(
2668 \\ A,2690 ++ default_enum_type ++
2669 \\ B,2691 \\) {
2670 \\ C,2692 \\ A,
2671 \\ _,2693 \\ B,
2672 \\};2694 \\ C,
2673 \\pub const A = @enumToInt(enum_SomeEnum.A);2695 \\ _,
2674 \\pub const B = @enumToInt(enum_SomeEnum.B);2696 \\};
2675 \\pub const C = @enumToInt(enum_SomeEnum.C);2697 \\pub const A = @enumToInt(enum_SomeEnum.A);
2676 \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {2698 \\pub const B = @enumToInt(enum_SomeEnum.B);
2677 \\ var a = arg_a;2699 \\pub const C = @enumToInt(enum_SomeEnum.C);
2678 \\ var b = arg_b;2700 \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
2679 \\ var c = arg_c;2701 \\ var a = arg_a;
2680 \\ var d = arg_d;2702 \\ var b = arg_b;
2681 \\ if (a != 0) return 0;2703 \\ var c = arg_c;
2682 \\ if (b != 0) return 1;2704 \\ var d = arg_d;
2683 \\ if (c != null) return 2;2705 \\ if (a != 0) return 0;
2684 \\ if (@enumToInt(d) != 0) return 3;2706 \\ if (b != 0) return 1;
2685 \\ return 4;2707 \\ if (c != null) return 2;
2686 \\}2708 \\ if (@enumToInt(d) != 0) return 3;
2709 \\ return 4;
2710 \\}
2687 });2711 });
26882712
2689 cases.add("simple data types",2713 cases.add("simple data types",
...@@ -3130,15 +3154,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3130,15 +3154,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3130 \\ Foo1,3154 \\ Foo1,
3131 \\};3155 \\};
3132 , &[_][]const u8{3156 , &[_][]const u8{
3133 \\pub const enum_Foo = extern enum(c_int) {3157 \\pub const enum_Foo = extern enum(
3134 \\ A = 2,3158 ++ default_enum_type ++
3135 \\ B = 5,3159 \\) {
3136 \\ @"1" = 6,3160 \\ A = 2,
3137 \\ _,3161 \\ B = 5,
3138 \\};3162 \\ @"1" = 6,
3139 \\pub const FooA = @enumToInt(enum_Foo.A);3163 \\ _,
3140 \\pub const FooB = @enumToInt(enum_Foo.B);3164 \\};
3141 \\pub const Foo1 = @enumToInt(enum_Foo.@"1");3165 \\pub const FooA = @enumToInt(enum_Foo.A);
3166 \\pub const FooB = @enumToInt(enum_Foo.B);
3167 \\pub const Foo1 = @enumToInt(enum_Foo.@"1");
3142 ,3168 ,
3143 \\pub const Foo = enum_Foo;3169 \\pub const Foo = enum_Foo;
3144 });3170 });