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
11171117 // default to the usual integer type used for all the enums.
11181118
11191119 // default to c_int since msvc and gcc default to different types
1120 const init_arg_expr = if (int_type.ptr != null and
1121 !isCBuiltinType(int_type, .UInt) and
1122 !isCBuiltinType(int_type, .Int))
1120 const init_arg_expr = if (int_type.ptr != null)
11231121 transQualType(c, scope, int_type, enum_loc) catch |err| switch (err) {
11241122 error.UnsupportedType => {
11251123 return failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
......@@ -2285,8 +2283,8 @@ fn transCCast(
22852283 // 1. If src_type is an enum, determine the underlying signed int type
22862284 // 2. Extend or truncate without changing signed-ness.
22872285 // 3. Bit-cast to correct signed-ness
2288 const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type);
22892286 const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);
2287 const src_type_is_signed = cIsSignedInteger(src_int_type);
22902288 var src_int_expr = if (cIsInteger(src_type)) expr else try Tag.enum_to_int.create(c.arena, expr);
22912289
22922290 if (isBoolRes(src_int_expr)) {
test/run_translated_c.zig+10
......@@ -1540,4 +1540,14 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
15401540 \\ return 0;
15411541 \\}
15421542 , "");
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 , "");
15431553}
test/translate_c.zig+174-148
......@@ -3,6 +3,8 @@ const std = @import("std");
33const CrossTarget = std.zig.CrossTarget;
44
55pub fn addCases(cases: *tests.TranslateCContext) void {
6 const default_enum_type = if (std.Target.current.abi == .msvc) "c_int" else "c_uint";
7
68 cases.add("field access is grouped if necessary",
79 \\unsigned long foo(unsigned long x) {
810 \\ return ((union{unsigned long _x}){x})._x;
......@@ -28,17 +30,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2830 \\ int a, b;
2931 \\} Bar;
3032 , &[_][]const u8{
31 \\pub const Foo = extern enum(c_int) {
32 \\ A,
33 \\ B,
34 \\ _,
35 \\};
36 \\pub const FooA = @enumToInt(Foo.A);
37 \\pub const FooB = @enumToInt(Foo.B);
38 \\pub const Bar = extern struct {
39 \\ a: c_int,
40 \\ b: c_int,
41 \\};
33 \\pub const Foo = extern enum(
34 ++ default_enum_type ++
35 \\) {
36 \\ A,
37 \\ B,
38 \\ _,
39 \\};
40 \\pub const FooA = @enumToInt(Foo.A);
41 \\pub const FooB = @enumToInt(Foo.B);
42 \\pub const Bar = extern struct {
43 \\ a: c_int,
44 \\ b: c_int,
45 \\};
4246 });
4347
4448 cases.add("if as while stmt has semicolon",
......@@ -118,29 +122,33 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
118122 \\}
119123 , &[_][]const u8{
120124 \\pub export fn foo() void {
121 \\ const enum_Foo = extern enum(c_int) {
122 \\ A,
123 \\ B,
124 \\ C,
125 \\ _,
126 \\ };
127 \\ const A = @enumToInt(enum_Foo.A);
128 \\ const B = @enumToInt(enum_Foo.B);
129 \\ const C = @enumToInt(enum_Foo.C);
130 \\ var a: enum_Foo = @import("std").meta.cast(enum_Foo, B);
131 \\ {
132 \\ const enum_Foo = extern enum(c_int) {
133 \\ A,
134 \\ B,
135 \\ C,
136 \\ _,
137 \\ };
138 \\ const A_2 = @enumToInt(enum_Foo.A);
139 \\ const B_3 = @enumToInt(enum_Foo.B);
140 \\ const C_4 = @enumToInt(enum_Foo.C);
141 \\ var a_5: enum_Foo = @import("std").meta.cast(enum_Foo, B_3);
142 \\ }
143 \\}
125 \\ const enum_Foo = extern enum(
126 ++ default_enum_type ++
127 \\) {
128 \\ A,
129 \\ B,
130 \\ C,
131 \\ _,
132 \\ };
133 \\ const A = @enumToInt(enum_Foo.A);
134 \\ const B = @enumToInt(enum_Foo.B);
135 \\ const C = @enumToInt(enum_Foo.C);
136 \\ var a: enum_Foo = @import("std").meta.cast(enum_Foo, B);
137 \\ {
138 \\ const enum_Foo = extern enum(
139 ++ default_enum_type ++
140 \\) {
141 \\ A,
142 \\ B,
143 \\ C,
144 \\ _,
145 \\ };
146 \\ const A_2 = @enumToInt(enum_Foo.A);
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 \\}
144152 });
145153
146154 cases.add("scoped record",
......@@ -1702,47 +1710,55 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17021710 \\ p,
17031711 \\};
17041712 , &[_][]const u8{
1705 \\pub const d = extern enum(c_int) {
1706 \\ a,
1707 \\ b,
1708 \\ c,
1709 \\ _,
1710 \\};
1711 \\pub const a = @enumToInt(d.a);
1712 \\pub const b = @enumToInt(d.b);
1713 \\pub const c = @enumToInt(d.c);
1714 \\const enum_unnamed_1 = extern enum(c_int) {
1715 \\ e = 0,
1716 \\ f = 4,
1717 \\ g = 5,
1718 \\ _,
1719 \\};
1720 \\pub const e = @enumToInt(enum_unnamed_1.e);
1721 \\pub const f = @enumToInt(enum_unnamed_1.f);
1722 \\pub const g = @enumToInt(enum_unnamed_1.g);
1723 \\pub export var h: enum_unnamed_1 = @import("std").meta.cast(enum_unnamed_1, e);
1724 \\const enum_unnamed_2 = extern enum(c_int) {
1725 \\ i,
1726 \\ j,
1727 \\ k,
1728 \\ _,
1729 \\};
1730 \\pub const i = @enumToInt(enum_unnamed_2.i);
1731 \\pub const j = @enumToInt(enum_unnamed_2.j);
1732 \\pub const k = @enumToInt(enum_unnamed_2.k);
1733 \\pub const struct_Baz = extern struct {
1734 \\ l: enum_unnamed_2,
1735 \\ m: d,
1736 \\};
1737 \\pub const enum_i = extern enum(c_int) {
1738 \\ n,
1739 \\ o,
1740 \\ p,
1741 \\ _,
1742 \\};
1743 \\pub const n = @enumToInt(enum_i.n);
1744 \\pub const o = @enumToInt(enum_i.o);
1745 \\pub const p = @enumToInt(enum_i.p);
1713 \\pub const d = extern enum(
1714 ++ default_enum_type ++
1715 \\) {
1716 \\ a,
1717 \\ b,
1718 \\ c,
1719 \\ _,
1720 \\};
1721 \\pub const a = @enumToInt(d.a);
1722 \\pub const b = @enumToInt(d.b);
1723 \\pub const c = @enumToInt(d.c);
1724 \\const enum_unnamed_1 = extern enum(
1725 ++ default_enum_type ++
1726 \\) {
1727 \\ e = 0,
1728 \\ f = 4,
1729 \\ g = 5,
1730 \\ _,
1731 \\};
1732 \\pub const e = @enumToInt(enum_unnamed_1.e);
1733 \\pub const f = @enumToInt(enum_unnamed_1.f);
1734 \\pub const g = @enumToInt(enum_unnamed_1.g);
1735 \\pub export var h: enum_unnamed_1 = @import("std").meta.cast(enum_unnamed_1, e);
1736 \\const enum_unnamed_2 = extern enum(
1737 ++ default_enum_type ++
1738 \\) {
1739 \\ i,
1740 \\ j,
1741 \\ k,
1742 \\ _,
1743 \\};
1744 \\pub const i = @enumToInt(enum_unnamed_2.i);
1745 \\pub const j = @enumToInt(enum_unnamed_2.j);
1746 \\pub const k = @enumToInt(enum_unnamed_2.k);
1747 \\pub const struct_Baz = extern struct {
1748 \\ l: enum_unnamed_2,
1749 \\ m: d,
1750 \\};
1751 \\pub const enum_i = extern enum(
1752 ++ default_enum_type ++
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);
17461762 ,
17471763 \\pub const Baz = struct_Baz;
17481764 });
......@@ -2234,13 +2250,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
22342250 \\ Two,
22352251 \\};
22362252 , &[_][]const u8{
2237 \\const enum_unnamed_1 = extern enum(c_int) {
2238 \\ One,
2239 \\ Two,
2240 \\ _,
2241 \\};
2242 \\pub const One = @enumToInt(enum_unnamed_1.One);
2243 \\pub const Two = @enumToInt(enum_unnamed_1.Two);
2253 \\const enum_unnamed_1 = extern enum(
2254 ++ default_enum_type ++
2255 \\) {
2256 \\ One,
2257 \\ Two,
2258 \\ _,
2259 \\};
2260 \\pub const One = @enumToInt(enum_unnamed_1.One);
2261 \\pub const Two = @enumToInt(enum_unnamed_1.Two);
22442262 });
22452263
22462264 cases.add("c style cast",
......@@ -2338,35 +2356,37 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
23382356 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
23392357 \\}
23402358 , &[_][]const u8{
2341 \\pub const enum_Foo = extern enum(c_int) {
2342 \\ A,
2343 \\ B,
2344 \\ C,
2345 \\ _,
2346 \\};
2347 \\pub const FooA = @enumToInt(enum_Foo.A);
2348 \\pub const FooB = @enumToInt(enum_Foo.B);
2349 \\pub const FooC = @enumToInt(enum_Foo.C);
2350 \\pub const SomeTypedef = c_int;
2351 \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
2352 \\ var a = arg_a;
2353 \\ var b = arg_b;
2354 \\ var c = arg_c;
2355 \\ var d: enum_Foo = @import("std").meta.cast(enum_Foo, FooA);
2356 \\ var e: c_int = @boolToInt((a != 0) and (b != 0));
2357 \\ var f: c_int = @boolToInt((b != 0) and (c != null));
2358 \\ var g: c_int = @boolToInt((a != 0) and (c != null));
2359 \\ var h: c_int = @boolToInt((a != 0) or (b != 0));
2360 \\ var i: c_int = @boolToInt((b != 0) or (c != null));
2361 \\ var j: c_int = @boolToInt((a != 0) or (c != null));
2362 \\ var k: c_int = @boolToInt((a != 0) or (@bitCast(c_int, @enumToInt(d)) != 0));
2363 \\ var l: c_int = @boolToInt((@bitCast(c_int, @enumToInt(d)) != 0) and (b != 0));
2364 \\ var m: c_int = @boolToInt((c != null) or (@bitCast(c_uint, @enumToInt(d)) != 0));
2365 \\ var td: SomeTypedef = 44;
2366 \\ var o: c_int = @boolToInt((td != 0) or (b != 0));
2367 \\ var p: c_int = @boolToInt((c != null) and (td != 0));
2368 \\ return (((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p;
2369 \\}
2359 \\pub const enum_Foo = extern enum(
2360 ++ default_enum_type ++
2361 \\) {
2362 \\ A,
2363 \\ B,
2364 \\ C,
2365 \\ _,
2366 \\};
2367 \\pub const FooA = @enumToInt(enum_Foo.A);
2368 \\pub const FooB = @enumToInt(enum_Foo.B);
2369 \\pub const FooC = @enumToInt(enum_Foo.C);
2370 \\pub const SomeTypedef = c_int;
2371 \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
2372 \\ var a = arg_a;
2373 \\ var b = arg_b;
2374 \\ var c = arg_c;
2375 \\ var d: enum_Foo = @import("std").meta.cast(enum_Foo, FooA);
2376 \\ var e: c_int = @boolToInt((a != 0) and (b != 0));
2377 \\ var f: c_int = @boolToInt((b != 0) and (c != null));
2378 \\ var g: c_int = @boolToInt((a != 0) and (c != null));
2379 \\ var h: c_int = @boolToInt((a != 0) or (b != 0));
2380 \\ var i: c_int = @boolToInt((b != 0) or (c != null));
2381 \\ var j: c_int = @boolToInt((a != 0) or (c != null));
2382 \\ var k: c_int = @boolToInt((a != 0) or (@bitCast(c_int, @enumToInt(d)) != 0));
2383 \\ var l: c_int = @boolToInt((@bitCast(c_int, @enumToInt(d)) != 0) and (b != 0));
2384 \\ var m: c_int = @boolToInt((c != null) or (@bitCast(c_uint, @enumToInt(d)) != 0));
2385 \\ var td: SomeTypedef = 44;
2386 \\ var o: c_int = @boolToInt((td != 0) or (b != 0));
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 \\}
23702390 ,
23712391 \\pub const Foo = enum_Foo;
23722392 });
......@@ -2387,14 +2407,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
23872407 \\ y: c_int,
23882408 \\};
23892409 ,
2390 \\pub const enum_Bar = extern enum(c_int) {
2391 \\ A,
2392 \\ B,
2393 \\ _,
2394 \\};
2395 \\pub const BarA = @enumToInt(enum_Bar.A);
2396 \\pub const BarB = @enumToInt(enum_Bar.B);
2397 \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
2410 \\pub const enum_Bar = extern enum(
2411 ++ default_enum_type ++
2412 \\) {
2413 \\ A,
2414 \\ B,
2415 \\ _,
2416 \\};
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;
23982420 ,
23992421 \\pub const Foo = struct_Foo;
24002422 \\pub const Bar = enum_Bar;
......@@ -2664,26 +2686,28 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
26642686 \\ return 4;
26652687 \\}
26662688 , &[_][]const u8{
2667 \\pub const enum_SomeEnum = extern enum(c_int) {
2668 \\ A,
2669 \\ B,
2670 \\ C,
2671 \\ _,
2672 \\};
2673 \\pub const A = @enumToInt(enum_SomeEnum.A);
2674 \\pub const B = @enumToInt(enum_SomeEnum.B);
2675 \\pub const C = @enumToInt(enum_SomeEnum.C);
2676 \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
2677 \\ var a = arg_a;
2678 \\ var b = arg_b;
2679 \\ var c = arg_c;
2680 \\ var d = arg_d;
2681 \\ if (a != 0) return 0;
2682 \\ if (b != 0) return 1;
2683 \\ if (c != null) return 2;
2684 \\ if (@enumToInt(d) != 0) return 3;
2685 \\ return 4;
2686 \\}
2689 \\pub const enum_SomeEnum = extern enum(
2690 ++ default_enum_type ++
2691 \\) {
2692 \\ A,
2693 \\ B,
2694 \\ C,
2695 \\ _,
2696 \\};
2697 \\pub const A = @enumToInt(enum_SomeEnum.A);
2698 \\pub const B = @enumToInt(enum_SomeEnum.B);
2699 \\pub const C = @enumToInt(enum_SomeEnum.C);
2700 \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
2701 \\ var a = arg_a;
2702 \\ var b = arg_b;
2703 \\ var c = arg_c;
2704 \\ var d = arg_d;
2705 \\ if (a != 0) return 0;
2706 \\ if (b != 0) return 1;
2707 \\ if (c != null) return 2;
2708 \\ if (@enumToInt(d) != 0) return 3;
2709 \\ return 4;
2710 \\}
26872711 });
26882712
26892713 cases.add("simple data types",
......@@ -3130,15 +3154,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
31303154 \\ Foo1,
31313155 \\};
31323156 , &[_][]const u8{
3133 \\pub const enum_Foo = extern enum(c_int) {
3134 \\ A = 2,
3135 \\ B = 5,
3136 \\ @"1" = 6,
3137 \\ _,
3138 \\};
3139 \\pub const FooA = @enumToInt(enum_Foo.A);
3140 \\pub const FooB = @enumToInt(enum_Foo.B);
3141 \\pub const Foo1 = @enumToInt(enum_Foo.@"1");
3157 \\pub const enum_Foo = extern enum(
3158 ++ default_enum_type ++
3159 \\) {
3160 \\ A = 2,
3161 \\ B = 5,
3162 \\ @"1" = 6,
3163 \\ _,
3164 \\};
3165 \\pub const FooA = @enumToInt(enum_Foo.A);
3166 \\pub const FooB = @enumToInt(enum_Foo.B);
3167 \\pub const Foo1 = @enumToInt(enum_Foo.@"1");
31423168 ,
31433169 \\pub const Foo = enum_Foo;
31443170 });