authorgravatar for evan@lagerdata.comEvan Haas <evan@lagerdata.com> 2021-06-18 17:36:50-07:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-23 08:44:25+03:00
log0e7897a9a2e8dff1ce869b78d5b6fda56f86bb05
treeee37a14f5b1d6a7a06eb5860d87d3eda9403035d
parentd1f99eabb745a3026b4bf0486ee542d38facee8b

translate-c: Remove usage of `extern enum`

Translate enum types as the underlying integer type. Translate enum constants as top-level integer constants of the correct type (which does not necessarily match the enum integer type). If an enum constant's type cannot be translated for some reason, omit it. See discussion https://github.com/ziglang/zig/issues/2115#issuecomment-827968279 Fixes #9153

8 files changed, 198 insertions(+), 435 deletions(-)

lib/std/zig/c_translation.zig+2-35
......@@ -11,7 +11,7 @@ const mem = std.mem;
1111
1212/// Given a type and value, cast the value to the type as c would.
1313pub fn cast(comptime DestType: type, target: anytype) DestType {
14 // this function should behave like transCCast in translate-c, except it's for macros and enums
14 // this function should behave like transCCast in translate-c, except it's for macros
1515 const SourceType = @TypeOf(target);
1616 switch (@typeInfo(DestType)) {
1717 .Fn, .Pointer => return castToPtr(DestType, SourceType, target),
......@@ -20,12 +20,6 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
2020 return castToPtr(DestType, SourceType, target);
2121 }
2222 },
23 .Enum => |enum_type| {
24 if (@typeInfo(SourceType) == .Int or @typeInfo(SourceType) == .ComptimeInt) {
25 const intermediate = cast(enum_type.tag_type, target);
26 return @intToEnum(DestType, intermediate);
27 }
28 },
2923 .Int => {
3024 switch (@typeInfo(SourceType)) {
3125 .Pointer => {
......@@ -36,9 +30,6 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
3630 return castInt(DestType, @ptrToInt(target));
3731 }
3832 },
39 .Enum => {
40 return castInt(DestType, @enumToInt(target));
41 },
4233 .Int => {
4334 return castInt(DestType, target);
4435 },
......@@ -106,12 +97,6 @@ fn ptrInfo(comptime PtrType: type) std.builtin.TypeInfo.Pointer {
10697}
10798
10899test "cast" {
109 const E = enum(u2) {
110 Zero,
111 One,
112 Two,
113 };
114
115100 var i = @as(i64, 10);
116101
117102 try testing.expect(cast(*u8, 16) == @intToPtr(*u8, 16));
......@@ -122,12 +107,9 @@ test "cast" {
122107 try testing.expect(cast(?*i64, @as(*align(1) i64, &i)) == &i);
123108 try testing.expect(cast(?*i64, @as(?*align(1) i64, &i)) == &i);
124109
125 try testing.expect(cast(E, 1) == .One);
126
127110 try testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(*u32, 4)));
128111 try testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(?*u32, 4)));
129112 try testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10)));
130 try testing.expectEqual(@as(u8, 2), cast(u8, E.Two));
131113
132114 try testing.expectEqual(@bitCast(i32, @as(u32, 0x8000_0000)), cast(i32, @as(u32, 0x8000_0000)));
133115
......@@ -136,17 +118,6 @@ test "cast" {
136118
137119 try testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2)));
138120
139 const C_ENUM = enum(c_int) {
140 A = 0,
141 B,
142 C,
143 _,
144 };
145 try testing.expectEqual(cast(C_ENUM, @as(i64, -1)), @intToEnum(C_ENUM, -1));
146 try testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B);
147 try testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B);
148 try testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42));
149
150121 var foo: c_int = -1;
151122 try testing.expect(cast(*c_void, -1) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1))));
152123 try testing.expect(cast(*c_void, foo) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1))));
......@@ -162,7 +133,7 @@ test "cast" {
162133pub fn sizeof(target: anytype) usize {
163134 const T: type = if (@TypeOf(target) == type) target else @TypeOf(target);
164135 switch (@typeInfo(T)) {
165 .Float, .Int, .Struct, .Union, .Enum, .Array, .Bool, .Vector => return @sizeOf(T),
136 .Float, .Int, .Struct, .Union, .Array, .Bool, .Vector => return @sizeOf(T),
166137 .Fn => {
167138 // sizeof(main) returns 1, sizeof(&main) returns pointer size.
168139 // We cannot distinguish those types in Zig, so use pointer size.
......@@ -228,7 +199,6 @@ pub fn sizeof(target: anytype) usize {
228199}
229200
230201test "sizeof" {
231 const E = enum(c_int) { One, _ };
232202 const S = extern struct { a: u32 };
233203
234204 const ptr_size = @sizeOf(*c_void);
......@@ -239,9 +209,6 @@ test "sizeof" {
239209
240210 try testing.expect(sizeof(2.0) == @sizeOf(f64));
241211
242 try testing.expect(sizeof(E) == @sizeOf(c_int));
243 try testing.expect(sizeof(E.One) == @sizeOf(c_int));
244
245212 try testing.expect(sizeof(S) == 4);
246213
247214 try testing.expect(sizeof([_]u32{ 4, 5, 6 }) == 12);
src/clang.zig-3
......@@ -389,9 +389,6 @@ pub const ElaboratedType = opaque {
389389};
390390
391391pub const EnumConstantDecl = opaque {
392 pub const getInitExpr = ZigClangEnumConstantDecl_getInitExpr;
393 extern fn ZigClangEnumConstantDecl_getInitExpr(*const EnumConstantDecl) ?*const Expr;
394
395392 pub const getInitVal = ZigClangEnumConstantDecl_getInitVal;
396393 extern fn ZigClangEnumConstantDecl_getInitVal(*const EnumConstantDecl) *const APSInt;
397394};
src/translate_c.zig+35-80
......@@ -1100,27 +1100,37 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E
11001100 }
11011101 name = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name});
11021102 }
1103 if (!toplevel) _ = try bs.makeMangledName(c, name);
1103 if (!toplevel) name = try bs.makeMangledName(c, name);
11041104 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name);
11051105
1106 const is_pub = toplevel and !is_unnamed;
1107 var redecls = std.ArrayList(Tag.enum_redecl.Data()).init(c.gpa);
1108 defer redecls.deinit();
1109
1110 const init_node = if (enum_decl.getDefinition()) |enum_def| blk: {
1111 var pure_enum = true;
1106 const enum_type_node = if (enum_decl.getDefinition()) |enum_def| blk: {
11121107 var it = enum_def.enumerator_begin();
1113 var end_it = enum_def.enumerator_end();
1108 const end_it = enum_def.enumerator_end();
11141109 while (it.neq(end_it)) : (it = it.next()) {
11151110 const enum_const = it.deref();
1116 if (enum_const.getInitExpr()) |_| {
1117 pure_enum = false;
1118 break;
1111 var enum_val_name: []const u8 = try c.str(@ptrCast(*const clang.NamedDecl, enum_const).getName_bytes_begin());
1112 if (!toplevel) {
1113 enum_val_name = try bs.makeMangledName(c, enum_val_name);
11191114 }
1120 }
11211115
1122 var fields = std.ArrayList(ast.Payload.Enum.Field).init(c.gpa);
1123 defer fields.deinit();
1116 const enum_const_qt = @ptrCast(*const clang.ValueDecl, enum_const).getType();
1117 const enum_const_loc = @ptrCast(*const clang.Decl, enum_const).getLocation();
1118 const enum_const_type_node: ?Node = transQualType(c, scope, enum_const_qt, enum_const_loc) catch |err| switch (err) {
1119 error.UnsupportedType => null,
1120 else => |e| return e,
1121 };
1122
1123 const enum_const_def = try Tag.enum_constant.create(c.arena, .{
1124 .name = enum_val_name,
1125 .is_public = toplevel,
1126 .type = enum_const_type_node,
1127 .value = try transCreateNodeAPInt(c, enum_const.getInitVal()),
1128 });
1129 if (toplevel)
1130 try addTopLevelDecl(c, enum_val_name, enum_const_def)
1131 else
1132 try scope.appendNode(enum_const_def);
1133 }
11241134
11251135 const int_type = enum_decl.getIntegerType();
11261136 // The underlying type may be null in case of forward-declared enum
......@@ -1128,61 +1138,27 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E
11281138 // default to the usual integer type used for all the enums.
11291139
11301140 // default to c_int since msvc and gcc default to different types
1131 const init_arg_expr = if (int_type.ptr != null)
1141 break :blk if (int_type.ptr != null)
11321142 transQualType(c, scope, int_type, enum_loc) catch |err| switch (err) {
11331143 error.UnsupportedType => {
1134 return failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
1144 return failDecl(c, enum_loc, name, "unable to translate enum integer type", .{});
11351145 },
11361146 else => |e| return e,
11371147 }
11381148 else
11391149 try Tag.type.create(c.arena, "c_int");
1140
1141 it = enum_def.enumerator_begin();
1142 end_it = enum_def.enumerator_end();
1143 while (it.neq(end_it)) : (it = it.next()) {
1144 const enum_const = it.deref();
1145 const enum_val_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_const).getName_bytes_begin());
1146
1147 const field_name = if (!is_unnamed and mem.startsWith(u8, enum_val_name, bare_name))
1148 enum_val_name[bare_name.len..]
1149 else
1150 enum_val_name;
1151
1152 const int_node = if (!pure_enum)
1153 try transCreateNodeAPInt(c, enum_const.getInitVal())
1154 else
1155 null;
1156
1157 try fields.append(.{
1158 .name = field_name,
1159 .value = int_node,
1160 });
1161
1162 // In C each enum value is in the global namespace. So we put them there too.
1163 // At this point we can rely on the enum emitting successfully.
1164 try redecls.append(.{
1165 .enum_val_name = enum_val_name,
1166 .field_name = field_name,
1167 .enum_name = name,
1168 });
1169 }
1170
1171 break :blk try Tag.@"enum".create(c.arena, .{
1172 .int_type = init_arg_expr,
1173 .fields = try c.arena.dupe(ast.Payload.Enum.Field, fields.items),
1174 });
11751150 } else blk: {
11761151 try c.opaque_demotes.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), {});
11771152 break :blk Tag.opaque_literal.init();
11781153 };
11791154
1155 const is_pub = toplevel and !is_unnamed;
11801156 const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
11811157 payload.* = .{
11821158 .base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
11831159 .data = .{
1160 .init = enum_type_node,
11841161 .name = name,
1185 .init = init_node,
11861162 },
11871163 };
11881164
......@@ -1193,18 +1169,6 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E
11931169 } else {
11941170 try scope.appendNode(Node.initPayload(&payload.base));
11951171 }
1196
1197 for (redecls.items) |redecl| {
1198 if (toplevel) {
1199 try addTopLevelDecl(c, redecl.field_name, try Tag.pub_enum_redecl.create(c.arena, redecl));
1200 } else {
1201 try scope.appendNode(try Tag.enum_redecl.create(c.arena, .{
1202 .enum_val_name = try bs.makeMangledName(c, redecl.enum_val_name),
1203 .field_name = redecl.field_name,
1204 .enum_name = redecl.enum_name,
1205 }));
1206 }
1207 }
12081172}
12091173
12101174const ResultUsed = enum {
......@@ -2098,8 +2062,7 @@ fn finishBoolExpr(
20982062 },
20992063 .Enum => {
21002064 // node != 0
2101 const int_val = try Tag.enum_to_int.create(c.arena, node);
2102 return Tag.not_equal.create(c.arena, .{ .lhs = int_val, .rhs = Tag.zero_literal.init() });
2065 return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.zero_literal.init() });
21032066 },
21042067 .Elaborated => {
21052068 const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);
......@@ -2312,21 +2275,22 @@ fn transCCast(
23122275 if (dst_type.eq(src_type)) return expr;
23132276 if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))
23142277 return transCPtrCast(c, scope, loc, dst_type, src_type, expr);
2278 if (cIsEnum(dst_type)) return transCCast(c, scope, loc, cIntTypeForEnum(dst_type), src_type, expr);
2279 if (cIsEnum(src_type)) return transCCast(c, scope, loc, dst_type, cIntTypeForEnum(src_type), expr);
23152280
23162281 const dst_node = try transQualType(c, scope, dst_type, loc);
2317 if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) {
2282 if (cIsInteger(dst_type) and cIsInteger(src_type)) {
23182283 // 1. If src_type is an enum, determine the underlying signed int type
23192284 // 2. Extend or truncate without changing signed-ness.
23202285 // 3. Bit-cast to correct signed-ness
2321 const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);
2322 const src_type_is_signed = cIsSignedInteger(src_int_type);
2323 var src_int_expr = if (cIsInteger(src_type)) expr else try Tag.enum_to_int.create(c.arena, expr);
2286 const src_type_is_signed = cIsSignedInteger(src_type);
2287 var src_int_expr = expr;
23242288
23252289 if (isBoolRes(src_int_expr)) {
23262290 src_int_expr = try Tag.bool_to_int.create(c.arena, src_int_expr);
23272291 }
23282292
2329 switch (cIntTypeCmp(dst_type, src_int_type)) {
2293 switch (cIntTypeCmp(dst_type, src_type)) {
23302294 .lt => {
23312295 // @truncate(SameSignSmallerInt, src_int_expr)
23322296 const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);
......@@ -2379,14 +2343,6 @@ fn transCCast(
23792343 const bool_to_int = try Tag.bool_to_int.create(c.arena, expr);
23802344 return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int });
23812345 }
2382 if (cIsEnum(dst_type)) {
2383 // import("std").meta.cast(dest_type, val)
2384 return Tag.helpers_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
2385 }
2386 if (cIsEnum(src_type) and !cIsEnum(dst_type)) {
2387 // @enumToInt(val)
2388 return Tag.enum_to_int.create(c.arena, expr);
2389 }
23902346 // @as(dest_type, val)
23912347 return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
23922348}
......@@ -5975,7 +5931,6 @@ fn getContainer(c: *Context, node: Node) ?Node {
59755931 switch (node.tag()) {
59765932 .@"union",
59775933 .@"struct",
5978 .@"enum",
59795934 .address_of,
59805935 .bit_not,
59815936 .not,
src/translate_c/ast.zig+22-119
......@@ -64,8 +64,6 @@ pub const Node = extern union {
6464 static_local_var,
6565 func,
6666 warning,
67 /// All enums are non-exhaustive
68 @"enum",
6967 @"struct",
7068 @"union",
7169 @"comptime",
......@@ -146,10 +144,6 @@ pub const Node = extern union {
146144 float_to_int,
147145 /// @intToFloat(lhs, rhs)
148146 int_to_float,
149 /// @intToEnum(lhs, rhs)
150 int_to_enum,
151 /// @enumToInt(operand)
152 enum_to_int,
153147 /// @intToPtr(lhs, rhs)
154148 int_to_ptr,
155149 /// @ptrToInt(operand)
......@@ -215,9 +209,8 @@ pub const Node = extern union {
215209 var_simple,
216210 /// pub const name = init;
217211 pub_var_simple,
218 /// pub const enum_field_name = @enumToInt(enum_name.field_name);
219 pub_enum_redecl,
220 enum_redecl,
212 /// pub? const name (: type)? = value
213 enum_constant,
221214
222215 /// pub inline fn name(params) return_type body
223216 pub_inline_fn,
......@@ -266,7 +259,6 @@ pub const Node = extern union {
266259 .unwrap,
267260 .deref,
268261 .ptr_to_int,
269 .enum_to_int,
270262 .empty_array,
271263 .while_true,
272264 .if_not_break,
......@@ -324,7 +316,6 @@ pub const Node = extern union {
324316 .float_cast,
325317 .float_to_int,
326318 .int_to_float,
327 .int_to_enum,
328319 .int_to_ptr,
329320 .array_cat,
330321 .ellipsis3,
......@@ -357,7 +348,6 @@ pub const Node = extern union {
357348 .call => Payload.Call,
358349 .var_decl => Payload.VarDecl,
359350 .func => Payload.Func,
360 .@"enum" => Payload.Enum,
361351 .@"struct", .@"union" => Payload.Record,
362352 .tuple => Payload.TupleInit,
363353 .container_init => Payload.ContainerInit,
......@@ -369,7 +359,7 @@ pub const Node = extern union {
369359 .arg_redecl, .alias, .fail_decl => Payload.ArgRedecl,
370360 .log2_int_type => Payload.Log2IntType,
371361 .var_simple, .pub_var_simple, .static_local_var => Payload.SimpleVarDecl,
372 .pub_enum_redecl, .enum_redecl => Payload.EnumRedecl,
362 .enum_constant => Payload.EnumConstant,
373363 .array_filler => Payload.ArrayFiller,
374364 .pub_inline_fn => Payload.PubInlineFn,
375365 .field_access => Payload.FieldAccess,
......@@ -554,19 +544,6 @@ pub const Payload = struct {
554544 type: Node,
555545 };
556546
557 pub const Enum = struct {
558 base: Payload,
559 data: struct {
560 int_type: Node,
561 fields: []Field,
562 },
563
564 pub const Field = struct {
565 name: []const u8,
566 value: ?Node,
567 };
568 };
569
570547 pub const Record = struct {
571548 base: Payload,
572549 data: struct {
......@@ -658,12 +635,13 @@ pub const Payload = struct {
658635 },
659636 };
660637
661 pub const EnumRedecl = struct {
638 pub const EnumConstant = struct {
662639 base: Payload,
663640 data: struct {
664 enum_val_name: []const u8,
665 field_name: []const u8,
666 enum_name: []const u8,
641 name: []const u8,
642 is_public: bool,
643 type: ?Node,
644 value: Node,
667645 },
668646 };
669647
......@@ -1307,14 +1285,6 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
13071285 const payload = node.castTag(.int_to_float).?.data;
13081286 return renderBuiltinCall(c, "@intToFloat", &.{ payload.lhs, payload.rhs });
13091287 },
1310 .int_to_enum => {
1311 const payload = node.castTag(.int_to_enum).?.data;
1312 return renderBuiltinCall(c, "@intToEnum", &.{ payload.lhs, payload.rhs });
1313 },
1314 .enum_to_int => {
1315 const payload = node.castTag(.enum_to_int).?.data;
1316 return renderBuiltinCall(c, "@enumToInt", &.{payload});
1317 },
13181288 .int_to_ptr => {
13191289 const payload = node.castTag(.int_to_ptr).?.data;
13201290 return renderBuiltinCall(c, "@intToPtr", &.{ payload.lhs, payload.rhs });
......@@ -1814,91 +1784,28 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
18141784 return renderFieldAccess(c, lhs, payload.field_name);
18151785 },
18161786 .@"struct", .@"union" => return renderRecord(c, node),
1817 .@"enum" => {
1818 const payload = node.castTag(.@"enum").?.data;
1819 _ = try c.addToken(.keyword_extern, "extern");
1820 const enum_tok = try c.addToken(.keyword_enum, "enum");
1821 _ = try c.addToken(.l_paren, "(");
1822 const arg_expr = try renderNode(c, payload.int_type);
1823 _ = try c.addToken(.r_paren, ")");
1824 _ = try c.addToken(.l_brace, "{");
1825 const members = try c.gpa.alloc(NodeIndex, payload.fields.len + 1);
1826 defer c.gpa.free(members);
1827 members[0] = 0;
1828
1829 for (payload.fields) |field, i| {
1830 const name_tok = try c.addIdentifier(field.name);
1831 const value_expr = if (field.value) |some| blk: {
1832 _ = try c.addToken(.equal, "=");
1833 break :blk try renderNode(c, some);
1834 } else 0;
1835
1836 members[i] = try c.addNode(.{
1837 .tag = .container_field_init,
1838 .main_token = name_tok,
1839 .data = .{
1840 .lhs = 0,
1841 .rhs = value_expr,
1842 },
1843 });
1844 _ = try c.addToken(.comma, ",");
1845 }
1846 // make non-exhaustive
1847 members[payload.fields.len] = try c.addNode(.{
1848 .tag = .container_field_init,
1849 .main_token = try c.addIdentifier("_"),
1850 .data = .{
1851 .lhs = 0,
1852 .rhs = 0,
1853 },
1854 });
1855 _ = try c.addToken(.comma, ",");
1856 _ = try c.addToken(.r_brace, "}");
1787 .enum_constant => {
1788 const payload = node.castTag(.enum_constant).?.data;
18571789
1858 const span = try c.listToSpan(members);
1859 return c.addNode(.{
1860 .tag = .container_decl_arg_trailing,
1861 .main_token = enum_tok,
1862 .data = .{
1863 .lhs = arg_expr,
1864 .rhs = try c.addExtra(NodeSubRange{
1865 .start = span.start,
1866 .end = span.end,
1867 }),
1868 },
1869 });
1870 },
1871 .pub_enum_redecl, .enum_redecl => {
1872 const payload = @fieldParentPtr(Payload.EnumRedecl, "base", node.ptr_otherwise).data;
1873 if (node.tag() == .pub_enum_redecl) _ = try c.addToken(.keyword_pub, "pub");
1790 if (payload.is_public) _ = try c.addToken(.keyword_pub, "pub");
18741791 const const_tok = try c.addToken(.keyword_const, "const");
1875 _ = try c.addIdentifier(payload.enum_val_name);
1792 _ = try c.addIdentifier(payload.name);
1793
1794 const type_node = if (payload.type) |enum_const_type| blk: {
1795 _ = try c.addToken(.colon, ":");
1796 break :blk try renderNode(c, enum_const_type);
1797 } else 0;
1798
18761799 _ = try c.addToken(.equal, "=");
18771800
1878 const enum_to_int_tok = try c.addToken(.builtin, "@enumToInt");
1879 _ = try c.addToken(.l_paren, "(");
1880 const enum_name = try c.addNode(.{
1881 .tag = .identifier,
1882 .main_token = try c.addIdentifier(payload.enum_name),
1883 .data = undefined,
1884 });
1885 const field_access = try renderFieldAccess(c, enum_name, payload.field_name);
1886 const init_node = try c.addNode(.{
1887 .tag = .builtin_call_two,
1888 .main_token = enum_to_int_tok,
1889 .data = .{
1890 .lhs = field_access,
1891 .rhs = 0,
1892 },
1893 });
1894 _ = try c.addToken(.r_paren, ")");
1801 const init_node = try renderNode(c, payload.value);
18951802 _ = try c.addToken(.semicolon, ";");
18961803
18971804 return c.addNode(.{
18981805 .tag = .simple_var_decl,
18991806 .main_token = const_tok,
19001807 .data = .{
1901 .lhs = 0,
1808 .lhs = type_node,
19021809 .rhs = init_node,
19031810 },
19041811 });
......@@ -2210,7 +2117,7 @@ fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIn
22102117fn addSemicolonIfNeeded(c: *Context, node: Node) !void {
22112118 switch (node.tag()) {
22122119 .warning => unreachable,
2213 .var_decl, .var_simple, .arg_redecl, .alias, .enum_redecl, .block, .empty_block, .block_single, .@"switch" => {},
2120 .var_decl, .var_simple, .arg_redecl, .alias, .block, .empty_block, .block_single, .@"switch" => {},
22142121 .while_true => {
22152122 const payload = node.castTag(.while_true).?.data;
22162123 return addSemicolonIfNotBlock(c, payload);
......@@ -2258,13 +2165,11 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
22582165 .float_cast,
22592166 .float_to_int,
22602167 .int_to_float,
2261 .int_to_enum,
22622168 .int_to_ptr,
22632169 .std_mem_zeroes,
22642170 .std_math_Log2Int,
22652171 .log2_int_type,
22662172 .ptr_to_int,
2267 .enum_to_int,
22682173 .sizeof,
22692174 .alignof,
22702175 .typeof,
......@@ -2340,7 +2245,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
23402245 .array_cat,
23412246 .array_filler,
23422247 .@"if",
2343 .@"enum",
23442248 .@"struct",
23452249 .@"union",
23462250 .array_init,
......@@ -2366,8 +2270,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
23662270 .alias,
23672271 .var_simple,
23682272 .pub_var_simple,
2369 .pub_enum_redecl,
2370 .enum_redecl,
2273 .enum_constant,
23712274 .@"while",
23722275 .@"switch",
23732276 .@"break",
src/zig_clang.cpp-6
......@@ -3228,12 +3228,6 @@ bool ZigClangEnumDecl_enumerator_iterator_neq(
32283228 return casted_a != casted_b;
32293229}
32303230
3231const struct ZigClangExpr *ZigClangEnumConstantDecl_getInitExpr(const struct ZigClangEnumConstantDecl *self) {
3232 auto casted = reinterpret_cast<const clang::EnumConstantDecl *>(self);
3233 const clang::Expr *result = casted->getInitExpr();
3234 return reinterpret_cast<const ZigClangExpr *>(result);
3235}
3236
32373231const struct ZigClangAPSInt *ZigClangEnumConstantDecl_getInitVal(const struct ZigClangEnumConstantDecl *self) {
32383232 auto casted = reinterpret_cast<const clang::EnumConstantDecl *>(self);
32393233 const llvm::APSInt *result = &casted->getInitVal();
src/zig_clang.h-1
......@@ -1326,6 +1326,5 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFieldDecl_getLocation(const s
13261326ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangFieldDecl_getParent(const struct ZigClangFieldDecl *);
13271327ZIG_EXTERN_C unsigned ZigClangFieldDecl_getFieldIndex(const struct ZigClangFieldDecl *);
13281328
1329ZIG_EXTERN_C const struct ZigClangExpr *ZigClangEnumConstantDecl_getInitExpr(const struct ZigClangEnumConstantDecl *);
13301329ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangEnumConstantDecl_getInitVal(const struct ZigClangEnumConstantDecl *);
13311330#endif
test/run_translated_c.zig+49
......@@ -1598,4 +1598,53 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
15981598 \\ return 0;
15991599 \\}
16001600 , "");
1601
1602 cases.add("Enum constants are assigned correct type. Issue #9153",
1603 \\enum A { A0, A1=0xFFFFFFFF };
1604 \\enum B { B0=-1, B1=0xFFFFFFFF };
1605 \\enum C { C0=-1, C1=0 };
1606 \\enum D { D0, D1=0xFFFFFFFFFFL };
1607 \\enum E { E0=-1, E1=0xFFFFFFFFFFL };
1608 \\int main(void) {
1609 \\ signed char a0 = A0, a1 = A1;
1610 \\ signed char b0 = B0, b1 = B1;
1611 \\ signed char c0 = C0, c1 = C1;
1612 \\ signed char d0 = D0, d1 = D1;
1613 \\ signed char e0 = E0, e1 = E1;
1614 \\ return 0;
1615 \\}
1616 , "");
1617
1618 cases.add("Enum constant matches enum name; multiple enumerations with same value",
1619 \\#include <stdlib.h>
1620 \\enum FOO {
1621 \\ FOO = 1,
1622 \\ BAR = 2,
1623 \\ BAZ = 1,
1624 \\};
1625 \\int main(void) {
1626 \\ enum FOO x = BAZ;
1627 \\ if (x != 1) abort();
1628 \\ if (x != BAZ) abort();
1629 \\ if (x != FOO) abort();
1630 \\}
1631 , "");
1632
1633 cases.add("Scoped enums",
1634 \\#include <stdlib.h>
1635 \\int main(void) {
1636 \\ enum Foo { A, B, C };
1637 \\ enum Foo a = B;
1638 \\ if (a != B) abort();
1639 \\ if (a != 1) abort();
1640 \\ {
1641 \\ enum Foo { A = 5, B = 6, C = 7 };
1642 \\ enum Foo a = B;
1643 \\ if (a != B) abort();
1644 \\ if (a != 6) abort();
1645 \\ }
1646 \\ if (a != B) abort();
1647 \\ if (a != 1) abort();
1648 \\}
1649 , "");
16011650}
test/translate_c.zig+90-191
......@@ -30,15 +30,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3030 \\ int a, b;
3131 \\} Bar;
3232 , &[_][]const u8{
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);
33 \\pub const FooA: c_int = 0;
34 \\pub const FooB: c_int = 1;
35 \\pub const Foo =
36 ++ " " ++ default_enum_type ++
37 \\;
4238 \\pub const Bar = extern struct {
4339 \\ a: c_int,
4440 \\ b: c_int,
......@@ -103,54 +99,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10399 \\pub const PTR = ?*c_void;
104100 });
105101
106 cases.add("scoped enum",
107 \\void foo() {
108 \\ enum Foo {
109 \\ A,
110 \\ B,
111 \\ C,
112 \\ };
113 \\ enum Foo a = B;
114 \\ {
115 \\ enum Foo {
116 \\ A,
117 \\ B,
118 \\ C,
119 \\ };
120 \\ enum Foo a = B;
121 \\ }
122 \\}
123 , &[_][]const u8{
124 \\pub export fn foo() void {
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").zig.c_translation.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").zig.c_translation.cast(enum_Foo, B_3);
150 \\ }
151 \\}
152 });
153
154102 cases.add("scoped record",
155103 \\void foo() {
156104 \\ struct Foo {
......@@ -1208,32 +1156,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12081156 \\ VAL23 = 0xFFFFFFFFFFFFFFFF,
12091157 \\};
12101158 , &[_][]const u8{
1211 \\pub const enum_EnumWithInits = extern enum(c_longlong) {
1212 \\ VAL01 = 0,
1213 \\ VAL02 = 1,
1214 \\ VAL03 = 2,
1215 \\ VAL04 = 3,
1216 \\ VAL05 = -1,
1217 \\ VAL06 = -2,
1218 \\ VAL07 = -3,
1219 \\ VAL08 = -4,
1220 \\ VAL09 = -3,
1221 \\ VAL10 = -1000012000,
1222 \\ VAL11 = -1000161000,
1223 \\ VAL12 = -1000174001,
1224 \\ VAL13 = -3,
1225 \\ VAL14 = -1000012000,
1226 \\ VAL15 = -1000161000,
1227 \\ VAL16 = -3,
1228 \\ VAL17 = 1000011998,
1229 \\ VAL18 = 1152921504606846976,
1230 \\ VAL19 = 3458764513820540927,
1231 \\ VAL20 = 6917529027641081854,
1232 \\ VAL21 = 6917529027641081853,
1233 \\ VAL22 = 0,
1234 \\ VAL23 = -1,
1235 \\ _,
1236 \\};
1159 \\pub const VAL01: c_int = 0;
1160 \\pub const VAL02: c_int = 1;
1161 \\pub const VAL03: c_int = 2;
1162 \\pub const VAL04: c_int = 3;
1163 \\pub const VAL05: c_int = -1;
1164 \\pub const VAL06: c_int = -2;
1165 \\pub const VAL07: c_int = -3;
1166 \\pub const VAL08: c_int = -4;
1167 \\pub const VAL09: c_int = -3;
1168 \\pub const VAL10: c_int = -1000012000;
1169 \\pub const VAL11: c_int = -1000161000;
1170 \\pub const VAL12: c_int = -1000174001;
1171 \\pub const VAL13: c_int = -3;
1172 \\pub const VAL14: c_int = -1000012000;
1173 \\pub const VAL15: c_int = -1000161000;
1174 \\pub const VAL16: c_int = -3;
1175 \\pub const VAL17: c_int = 1000011998;
1176 \\pub const VAL18: c_longlong = 1152921504606846976;
1177 \\pub const VAL19: c_longlong = 3458764513820540927;
1178 \\pub const VAL20: c_longlong = 6917529027641081854;
1179 \\pub const VAL21: c_longlong = 6917529027641081853;
1180 \\pub const VAL22: c_int = 0;
1181 \\pub const VAL23: c_longlong = -1;
1182 \\pub const enum_EnumWithInits = c_longlong;
12371183 });
12381184 }
12391185
......@@ -1591,11 +1537,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15911537 \\extern enum enum_ty my_enum;
15921538 \\enum enum_ty { FOO };
15931539 , &[_][]const u8{
1594 \\pub const enum_enum_ty = extern enum(c_int) {
1595 \\ FOO,
1596 \\ _,
1597 \\};
1598 \\pub const FOO = @enumToInt(enum_enum_ty.FOO);
1540 \\pub const FOO: c_int = 0;
1541 \\pub const enum_enum_ty = c_int;
15991542 \\pub extern var my_enum: enum_enum_ty;
16001543 });
16011544
......@@ -1716,57 +1659,37 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17161659 \\ p,
17171660 \\};
17181661 , &[_][]const u8{
1719 \\pub const d = extern enum(
1720 ++ default_enum_type ++
1721 \\) {
1722 \\ a,
1723 \\ b,
1724 \\ c,
1725 \\ _,
1726 \\};
1727 \\pub const a = @enumToInt(d.a);
1728 \\pub const b = @enumToInt(d.b);
1729 \\pub const c = @enumToInt(d.c);
1730 \\const enum_unnamed_1 = extern enum(
1731 ++ default_enum_type ++
1732 \\) {
1733 \\ e = 0,
1734 \\ f = 4,
1735 \\ g = 5,
1736 \\ _,
1737 \\};
1738 \\pub const e = @enumToInt(enum_unnamed_1.e);
1739 \\pub const f = @enumToInt(enum_unnamed_1.f);
1740 \\pub const g = @enumToInt(enum_unnamed_1.g);
1741 \\pub export var h: enum_unnamed_1 = @import("std").zig.c_translation.cast(enum_unnamed_1, e);
1742 \\const enum_unnamed_2 = extern enum(
1743 ++ default_enum_type ++
1744 \\) {
1745 \\ i,
1746 \\ j,
1747 \\ k,
1748 \\ _,
1749 \\};
1750 \\pub const i = @enumToInt(enum_unnamed_2.i);
1751 \\pub const j = @enumToInt(enum_unnamed_2.j);
1752 \\pub const k = @enumToInt(enum_unnamed_2.k);
1662 \\pub const a: c_int = 0;
1663 \\pub const b: c_int = 1;
1664 \\pub const c: c_int = 2;
1665 \\pub const d =
1666 ++ " " ++ default_enum_type ++
1667 \\;
1668 \\pub const e: c_int = 0;
1669 \\pub const f: c_int = 4;
1670 \\pub const g: c_int = 5;
1671 \\const enum_unnamed_1 =
1672 ++ " " ++ default_enum_type ++
1673 \\;
1674 \\pub export var h: enum_unnamed_1 = @bitCast(c_uint, e);
1675 \\pub const i: c_int = 0;
1676 \\pub const j: c_int = 1;
1677 \\pub const k: c_int = 2;
1678 \\const enum_unnamed_2 =
1679 ++ " " ++ default_enum_type ++
1680 \\;
17531681 \\pub const struct_Baz = extern struct {
17541682 \\ l: enum_unnamed_2,
17551683 \\ m: d,
17561684 \\};
1757 \\pub const enum_i = extern enum(
1758 ++ default_enum_type ++
1759 \\) {
1760 \\ n,
1761 \\ o,
1762 \\ p,
1763 \\ _,
1764 \\};
1765 \\pub const n = @enumToInt(enum_i.n);
1766 \\pub const o = @enumToInt(enum_i.o);
1767 \\pub const p = @enumToInt(enum_i.p);
1685 \\pub const n: c_int = 0;
1686 \\pub const o: c_int = 1;
1687 \\pub const p: c_int = 2;
1688 \\pub const enum_i =
1689 ++ " " ++ default_enum_type ++
1690 \\;
17681691 ,
1769 \\pub const Baz = struct_Baz;
1692 "pub const Baz = struct_Baz;",
17701693 });
17711694
17721695 cases.add("#define a char literal",
......@@ -2257,15 +2180,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
22572180 \\ Two,
22582181 \\};
22592182 , &[_][]const u8{
2260 \\const enum_unnamed_1 = extern enum(
2261 ++ default_enum_type ++
2262 \\) {
2263 \\ One,
2264 \\ Two,
2265 \\ _,
2266 \\};
2267 \\pub const One = @enumToInt(enum_unnamed_1.One);
2268 \\pub const Two = @enumToInt(enum_unnamed_1.Two);
2183 \\pub const One: c_int = 0;
2184 \\pub const Two: c_int = 1;
2185 \\const enum_unnamed_1 =
2186 ++ " " ++ default_enum_type ++
2187 \\;
22692188 });
22702189
22712190 cases.add("c style cast",
......@@ -2363,32 +2282,27 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
23632282 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
23642283 \\}
23652284 , &[_][]const u8{
2366 \\pub const enum_Foo = extern enum(
2367 ++ default_enum_type ++
2368 \\) {
2369 \\ A,
2370 \\ B,
2371 \\ C,
2372 \\ _,
2373 \\};
2374 \\pub const FooA = @enumToInt(enum_Foo.A);
2375 \\pub const FooB = @enumToInt(enum_Foo.B);
2376 \\pub const FooC = @enumToInt(enum_Foo.C);
2285 \\pub const FooA: c_int = 0;
2286 \\pub const FooB: c_int = 1;
2287 \\pub const FooC: c_int = 2;
2288 \\pub const enum_Foo =
2289 ++ " " ++ default_enum_type ++
2290 \\;
23772291 \\pub const SomeTypedef = c_int;
23782292 \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
23792293 \\ var a = arg_a;
23802294 \\ var b = arg_b;
23812295 \\ var c = arg_c;
2382 \\ var d: enum_Foo = @import("std").zig.c_translation.cast(enum_Foo, FooA);
2296 \\ var d: enum_Foo = @bitCast(c_uint, FooA);
23832297 \\ var e: c_int = @boolToInt((a != 0) and (b != 0));
23842298 \\ var f: c_int = @boolToInt((b != 0) and (c != null));
23852299 \\ var g: c_int = @boolToInt((a != 0) and (c != null));
23862300 \\ var h: c_int = @boolToInt((a != 0) or (b != 0));
23872301 \\ var i: c_int = @boolToInt((b != 0) or (c != null));
23882302 \\ var j: c_int = @boolToInt((a != 0) or (c != null));
2389 \\ var k: c_int = @boolToInt((a != 0) or (@bitCast(c_int, @enumToInt(d)) != 0));
2390 \\ var l: c_int = @boolToInt((@bitCast(c_int, @enumToInt(d)) != 0) and (b != 0));
2391 \\ var m: c_int = @boolToInt((c != null) or (@bitCast(c_uint, @enumToInt(d)) != 0));
2303 \\ var k: c_int = @boolToInt((a != 0) or (@bitCast(c_int, d) != 0));
2304 \\ var l: c_int = @boolToInt((@bitCast(c_int, d) != 0) and (b != 0));
2305 \\ var m: c_int = @boolToInt((c != null) or (d != 0));
23922306 \\ var td: SomeTypedef = 44;
23932307 \\ var o: c_int = @boolToInt((td != 0) or (b != 0));
23942308 \\ var p: c_int = @boolToInt((c != null) and (td != 0));
......@@ -2413,16 +2327,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
24132327 \\ x: c_int,
24142328 \\ y: c_int,
24152329 \\};
2416 ,
2417 \\pub const enum_Bar = extern enum(
2418 ++ default_enum_type ++
2419 \\) {
2420 \\ A,
2421 \\ B,
2422 \\ _,
2423 \\};
2424 \\pub const BarA = @enumToInt(enum_Bar.A);
2425 \\pub const BarB = @enumToInt(enum_Bar.B);
2330 \\pub const BarA: c_int = 0;
2331 \\pub const BarB: c_int = 1;
2332 \\pub const enum_Bar =
2333 ++ " " ++ default_enum_type ++
2334 \\;
24262335 \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
24272336 ,
24282337 \\pub const Foo = struct_Foo;
......@@ -2693,17 +2602,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
26932602 \\ return 4;
26942603 \\}
26952604 , &[_][]const u8{
2696 \\pub const enum_SomeEnum = extern enum(
2697 ++ default_enum_type ++
2698 \\) {
2699 \\ A,
2700 \\ B,
2701 \\ C,
2702 \\ _,
2703 \\};
2704 \\pub const A = @enumToInt(enum_SomeEnum.A);
2705 \\pub const B = @enumToInt(enum_SomeEnum.B);
2706 \\pub const C = @enumToInt(enum_SomeEnum.C);
2605 \\pub const A: c_int = 0;
2606 \\pub const B: c_int = 1;
2607 \\pub const C: c_int = 2;
2608 \\pub const enum_SomeEnum =
2609 ++ " " ++ default_enum_type ++
2610 \\;
27072611 \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
27082612 \\ var a = arg_a;
27092613 \\ var b = arg_b;
......@@ -2712,7 +2616,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
27122616 \\ if (a != 0) return 0;
27132617 \\ if (b != 0) return 1;
27142618 \\ if (c != null) return 2;
2715 \\ if (@enumToInt(d) != 0) return 3;
2619 \\ if (d != 0) return 3;
27162620 \\ return 4;
27172621 \\}
27182622 });
......@@ -3161,17 +3065,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
31613065 \\ Foo1,
31623066 \\};
31633067 , &[_][]const u8{
3164 \\pub const enum_Foo = extern enum(
3165 ++ default_enum_type ++
3166 \\) {
3167 \\ A = 2,
3168 \\ B = 5,
3169 \\ @"1" = 6,
3170 \\ _,
3171 \\};
3172 \\pub const FooA = @enumToInt(enum_Foo.A);
3173 \\pub const FooB = @enumToInt(enum_Foo.B);
3174 \\pub const Foo1 = @enumToInt(enum_Foo.@"1");
3068 \\pub const FooA: c_int = 2;
3069 \\pub const FooB: c_int = 5;
3070 \\pub const Foo1: c_int = 6;
3071 \\pub const enum_Foo =
3072 ++ " " ++ default_enum_type ++
3073 \\;
31753074 ,
31763075 \\pub const Foo = enum_Foo;
31773076 });