Commit 0e7897a9a2
Changed files (8)
lib
std
src
lib/std/zig/c_translation.zig
@@ -11,7 +11,7 @@ const mem = std.mem;
/// Given a type and value, cast the value to the type as c would.
pub fn cast(comptime DestType: type, target: anytype) DestType {
- // this function should behave like transCCast in translate-c, except it's for macros and enums
+ // this function should behave like transCCast in translate-c, except it's for macros
const SourceType = @TypeOf(target);
switch (@typeInfo(DestType)) {
.Fn, .Pointer => return castToPtr(DestType, SourceType, target),
@@ -20,12 +20,6 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
return castToPtr(DestType, SourceType, target);
}
},
- .Enum => |enum_type| {
- if (@typeInfo(SourceType) == .Int or @typeInfo(SourceType) == .ComptimeInt) {
- const intermediate = cast(enum_type.tag_type, target);
- return @intToEnum(DestType, intermediate);
- }
- },
.Int => {
switch (@typeInfo(SourceType)) {
.Pointer => {
@@ -36,9 +30,6 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
return castInt(DestType, @ptrToInt(target));
}
},
- .Enum => {
- return castInt(DestType, @enumToInt(target));
- },
.Int => {
return castInt(DestType, target);
},
@@ -106,12 +97,6 @@ fn ptrInfo(comptime PtrType: type) std.builtin.TypeInfo.Pointer {
}
test "cast" {
- const E = enum(u2) {
- Zero,
- One,
- Two,
- };
-
var i = @as(i64, 10);
try testing.expect(cast(*u8, 16) == @intToPtr(*u8, 16));
@@ -122,12 +107,9 @@ test "cast" {
try testing.expect(cast(?*i64, @as(*align(1) i64, &i)) == &i);
try testing.expect(cast(?*i64, @as(?*align(1) i64, &i)) == &i);
- try testing.expect(cast(E, 1) == .One);
-
try testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(*u32, 4)));
try testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(?*u32, 4)));
try testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10)));
- try testing.expectEqual(@as(u8, 2), cast(u8, E.Two));
try testing.expectEqual(@bitCast(i32, @as(u32, 0x8000_0000)), cast(i32, @as(u32, 0x8000_0000)));
@@ -136,17 +118,6 @@ test "cast" {
try testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2)));
- const C_ENUM = enum(c_int) {
- A = 0,
- B,
- C,
- _,
- };
- try testing.expectEqual(cast(C_ENUM, @as(i64, -1)), @intToEnum(C_ENUM, -1));
- try testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B);
- try testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B);
- try testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42));
-
var foo: c_int = -1;
try testing.expect(cast(*c_void, -1) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1))));
try testing.expect(cast(*c_void, foo) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1))));
@@ -162,7 +133,7 @@ test "cast" {
pub fn sizeof(target: anytype) usize {
const T: type = if (@TypeOf(target) == type) target else @TypeOf(target);
switch (@typeInfo(T)) {
- .Float, .Int, .Struct, .Union, .Enum, .Array, .Bool, .Vector => return @sizeOf(T),
+ .Float, .Int, .Struct, .Union, .Array, .Bool, .Vector => return @sizeOf(T),
.Fn => {
// sizeof(main) returns 1, sizeof(&main) returns pointer size.
// We cannot distinguish those types in Zig, so use pointer size.
@@ -228,7 +199,6 @@ pub fn sizeof(target: anytype) usize {
}
test "sizeof" {
- const E = enum(c_int) { One, _ };
const S = extern struct { a: u32 };
const ptr_size = @sizeOf(*c_void);
@@ -239,9 +209,6 @@ test "sizeof" {
try testing.expect(sizeof(2.0) == @sizeOf(f64));
- try testing.expect(sizeof(E) == @sizeOf(c_int));
- try testing.expect(sizeof(E.One) == @sizeOf(c_int));
-
try testing.expect(sizeof(S) == 4);
try testing.expect(sizeof([_]u32{ 4, 5, 6 }) == 12);
src/translate_c/ast.zig
@@ -64,8 +64,6 @@ pub const Node = extern union {
static_local_var,
func,
warning,
- /// All enums are non-exhaustive
- @"enum",
@"struct",
@"union",
@"comptime",
@@ -146,10 +144,6 @@ pub const Node = extern union {
float_to_int,
/// @intToFloat(lhs, rhs)
int_to_float,
- /// @intToEnum(lhs, rhs)
- int_to_enum,
- /// @enumToInt(operand)
- enum_to_int,
/// @intToPtr(lhs, rhs)
int_to_ptr,
/// @ptrToInt(operand)
@@ -215,9 +209,8 @@ pub const Node = extern union {
var_simple,
/// pub const name = init;
pub_var_simple,
- /// pub const enum_field_name = @enumToInt(enum_name.field_name);
- pub_enum_redecl,
- enum_redecl,
+ /// pub? const name (: type)? = value
+ enum_constant,
/// pub inline fn name(params) return_type body
pub_inline_fn,
@@ -266,7 +259,6 @@ pub const Node = extern union {
.unwrap,
.deref,
.ptr_to_int,
- .enum_to_int,
.empty_array,
.while_true,
.if_not_break,
@@ -324,7 +316,6 @@ pub const Node = extern union {
.float_cast,
.float_to_int,
.int_to_float,
- .int_to_enum,
.int_to_ptr,
.array_cat,
.ellipsis3,
@@ -357,7 +348,6 @@ pub const Node = extern union {
.call => Payload.Call,
.var_decl => Payload.VarDecl,
.func => Payload.Func,
- .@"enum" => Payload.Enum,
.@"struct", .@"union" => Payload.Record,
.tuple => Payload.TupleInit,
.container_init => Payload.ContainerInit,
@@ -369,7 +359,7 @@ pub const Node = extern union {
.arg_redecl, .alias, .fail_decl => Payload.ArgRedecl,
.log2_int_type => Payload.Log2IntType,
.var_simple, .pub_var_simple, .static_local_var => Payload.SimpleVarDecl,
- .pub_enum_redecl, .enum_redecl => Payload.EnumRedecl,
+ .enum_constant => Payload.EnumConstant,
.array_filler => Payload.ArrayFiller,
.pub_inline_fn => Payload.PubInlineFn,
.field_access => Payload.FieldAccess,
@@ -554,19 +544,6 @@ pub const Payload = struct {
type: Node,
};
- pub const Enum = struct {
- base: Payload,
- data: struct {
- int_type: Node,
- fields: []Field,
- },
-
- pub const Field = struct {
- name: []const u8,
- value: ?Node,
- };
- };
-
pub const Record = struct {
base: Payload,
data: struct {
@@ -658,12 +635,13 @@ pub const Payload = struct {
},
};
- pub const EnumRedecl = struct {
+ pub const EnumConstant = struct {
base: Payload,
data: struct {
- enum_val_name: []const u8,
- field_name: []const u8,
- enum_name: []const u8,
+ name: []const u8,
+ is_public: bool,
+ type: ?Node,
+ value: Node,
},
};
@@ -1307,14 +1285,6 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
const payload = node.castTag(.int_to_float).?.data;
return renderBuiltinCall(c, "@intToFloat", &.{ payload.lhs, payload.rhs });
},
- .int_to_enum => {
- const payload = node.castTag(.int_to_enum).?.data;
- return renderBuiltinCall(c, "@intToEnum", &.{ payload.lhs, payload.rhs });
- },
- .enum_to_int => {
- const payload = node.castTag(.enum_to_int).?.data;
- return renderBuiltinCall(c, "@enumToInt", &.{payload});
- },
.int_to_ptr => {
const payload = node.castTag(.int_to_ptr).?.data;
return renderBuiltinCall(c, "@intToPtr", &.{ payload.lhs, payload.rhs });
@@ -1814,91 +1784,28 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
return renderFieldAccess(c, lhs, payload.field_name);
},
.@"struct", .@"union" => return renderRecord(c, node),
- .@"enum" => {
- const payload = node.castTag(.@"enum").?.data;
- _ = try c.addToken(.keyword_extern, "extern");
- const enum_tok = try c.addToken(.keyword_enum, "enum");
- _ = try c.addToken(.l_paren, "(");
- const arg_expr = try renderNode(c, payload.int_type);
- _ = try c.addToken(.r_paren, ")");
- _ = try c.addToken(.l_brace, "{");
- const members = try c.gpa.alloc(NodeIndex, payload.fields.len + 1);
- defer c.gpa.free(members);
- members[0] = 0;
-
- for (payload.fields) |field, i| {
- const name_tok = try c.addIdentifier(field.name);
- const value_expr = if (field.value) |some| blk: {
- _ = try c.addToken(.equal, "=");
- break :blk try renderNode(c, some);
- } else 0;
-
- members[i] = try c.addNode(.{
- .tag = .container_field_init,
- .main_token = name_tok,
- .data = .{
- .lhs = 0,
- .rhs = value_expr,
- },
- });
- _ = try c.addToken(.comma, ",");
- }
- // make non-exhaustive
- members[payload.fields.len] = try c.addNode(.{
- .tag = .container_field_init,
- .main_token = try c.addIdentifier("_"),
- .data = .{
- .lhs = 0,
- .rhs = 0,
- },
- });
- _ = try c.addToken(.comma, ",");
- _ = try c.addToken(.r_brace, "}");
+ .enum_constant => {
+ const payload = node.castTag(.enum_constant).?.data;
- const span = try c.listToSpan(members);
- return c.addNode(.{
- .tag = .container_decl_arg_trailing,
- .main_token = enum_tok,
- .data = .{
- .lhs = arg_expr,
- .rhs = try c.addExtra(NodeSubRange{
- .start = span.start,
- .end = span.end,
- }),
- },
- });
- },
- .pub_enum_redecl, .enum_redecl => {
- const payload = @fieldParentPtr(Payload.EnumRedecl, "base", node.ptr_otherwise).data;
- if (node.tag() == .pub_enum_redecl) _ = try c.addToken(.keyword_pub, "pub");
+ if (payload.is_public) _ = try c.addToken(.keyword_pub, "pub");
const const_tok = try c.addToken(.keyword_const, "const");
- _ = try c.addIdentifier(payload.enum_val_name);
+ _ = try c.addIdentifier(payload.name);
+
+ const type_node = if (payload.type) |enum_const_type| blk: {
+ _ = try c.addToken(.colon, ":");
+ break :blk try renderNode(c, enum_const_type);
+ } else 0;
+
_ = try c.addToken(.equal, "=");
- const enum_to_int_tok = try c.addToken(.builtin, "@enumToInt");
- _ = try c.addToken(.l_paren, "(");
- const enum_name = try c.addNode(.{
- .tag = .identifier,
- .main_token = try c.addIdentifier(payload.enum_name),
- .data = undefined,
- });
- const field_access = try renderFieldAccess(c, enum_name, payload.field_name);
- const init_node = try c.addNode(.{
- .tag = .builtin_call_two,
- .main_token = enum_to_int_tok,
- .data = .{
- .lhs = field_access,
- .rhs = 0,
- },
- });
- _ = try c.addToken(.r_paren, ")");
+ const init_node = try renderNode(c, payload.value);
_ = try c.addToken(.semicolon, ";");
return c.addNode(.{
.tag = .simple_var_decl,
.main_token = const_tok,
.data = .{
- .lhs = 0,
+ .lhs = type_node,
.rhs = init_node,
},
});
@@ -2210,7 +2117,7 @@ fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIn
fn addSemicolonIfNeeded(c: *Context, node: Node) !void {
switch (node.tag()) {
.warning => unreachable,
- .var_decl, .var_simple, .arg_redecl, .alias, .enum_redecl, .block, .empty_block, .block_single, .@"switch" => {},
+ .var_decl, .var_simple, .arg_redecl, .alias, .block, .empty_block, .block_single, .@"switch" => {},
.while_true => {
const payload = node.castTag(.while_true).?.data;
return addSemicolonIfNotBlock(c, payload);
@@ -2258,13 +2165,11 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.float_cast,
.float_to_int,
.int_to_float,
- .int_to_enum,
.int_to_ptr,
.std_mem_zeroes,
.std_math_Log2Int,
.log2_int_type,
.ptr_to_int,
- .enum_to_int,
.sizeof,
.alignof,
.typeof,
@@ -2340,7 +2245,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.array_cat,
.array_filler,
.@"if",
- .@"enum",
.@"struct",
.@"union",
.array_init,
@@ -2366,8 +2270,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
.alias,
.var_simple,
.pub_var_simple,
- .pub_enum_redecl,
- .enum_redecl,
+ .enum_constant,
.@"while",
.@"switch",
.@"break",
src/clang.zig
@@ -389,9 +389,6 @@ pub const ElaboratedType = opaque {
};
pub const EnumConstantDecl = opaque {
- pub const getInitExpr = ZigClangEnumConstantDecl_getInitExpr;
- extern fn ZigClangEnumConstantDecl_getInitExpr(*const EnumConstantDecl) ?*const Expr;
-
pub const getInitVal = ZigClangEnumConstantDecl_getInitVal;
extern fn ZigClangEnumConstantDecl_getInitVal(*const EnumConstantDecl) *const APSInt;
};
src/translate_c.zig
@@ -1100,27 +1100,37 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E
}
name = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name});
}
- if (!toplevel) _ = try bs.makeMangledName(c, name);
+ if (!toplevel) name = try bs.makeMangledName(c, name);
try c.decl_table.putNoClobber(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name);
- const is_pub = toplevel and !is_unnamed;
- var redecls = std.ArrayList(Tag.enum_redecl.Data()).init(c.gpa);
- defer redecls.deinit();
-
- const init_node = if (enum_decl.getDefinition()) |enum_def| blk: {
- var pure_enum = true;
+ const enum_type_node = if (enum_decl.getDefinition()) |enum_def| blk: {
var it = enum_def.enumerator_begin();
- var end_it = enum_def.enumerator_end();
+ const end_it = enum_def.enumerator_end();
while (it.neq(end_it)) : (it = it.next()) {
const enum_const = it.deref();
- if (enum_const.getInitExpr()) |_| {
- pure_enum = false;
- break;
+ var enum_val_name: []const u8 = try c.str(@ptrCast(*const clang.NamedDecl, enum_const).getName_bytes_begin());
+ if (!toplevel) {
+ enum_val_name = try bs.makeMangledName(c, enum_val_name);
}
- }
- var fields = std.ArrayList(ast.Payload.Enum.Field).init(c.gpa);
- defer fields.deinit();
+ const enum_const_qt = @ptrCast(*const clang.ValueDecl, enum_const).getType();
+ const enum_const_loc = @ptrCast(*const clang.Decl, enum_const).getLocation();
+ const enum_const_type_node: ?Node = transQualType(c, scope, enum_const_qt, enum_const_loc) catch |err| switch (err) {
+ error.UnsupportedType => null,
+ else => |e| return e,
+ };
+
+ const enum_const_def = try Tag.enum_constant.create(c.arena, .{
+ .name = enum_val_name,
+ .is_public = toplevel,
+ .type = enum_const_type_node,
+ .value = try transCreateNodeAPInt(c, enum_const.getInitVal()),
+ });
+ if (toplevel)
+ try addTopLevelDecl(c, enum_val_name, enum_const_def)
+ else
+ try scope.appendNode(enum_const_def);
+ }
const int_type = enum_decl.getIntegerType();
// 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
// default to the usual integer type used for all the enums.
// default to c_int since msvc and gcc default to different types
- const init_arg_expr = if (int_type.ptr != null)
+ break :blk if (int_type.ptr != null)
transQualType(c, scope, int_type, enum_loc) catch |err| switch (err) {
error.UnsupportedType => {
- return failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
+ return failDecl(c, enum_loc, name, "unable to translate enum integer type", .{});
},
else => |e| return e,
}
else
try Tag.type.create(c.arena, "c_int");
-
- it = enum_def.enumerator_begin();
- end_it = enum_def.enumerator_end();
- while (it.neq(end_it)) : (it = it.next()) {
- const enum_const = it.deref();
- const enum_val_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_const).getName_bytes_begin());
-
- const field_name = if (!is_unnamed and mem.startsWith(u8, enum_val_name, bare_name))
- enum_val_name[bare_name.len..]
- else
- enum_val_name;
-
- const int_node = if (!pure_enum)
- try transCreateNodeAPInt(c, enum_const.getInitVal())
- else
- null;
-
- try fields.append(.{
- .name = field_name,
- .value = int_node,
- });
-
- // In C each enum value is in the global namespace. So we put them there too.
- // At this point we can rely on the enum emitting successfully.
- try redecls.append(.{
- .enum_val_name = enum_val_name,
- .field_name = field_name,
- .enum_name = name,
- });
- }
-
- break :blk try Tag.@"enum".create(c.arena, .{
- .int_type = init_arg_expr,
- .fields = try c.arena.dupe(ast.Payload.Enum.Field, fields.items),
- });
} else blk: {
try c.opaque_demotes.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), {});
break :blk Tag.opaque_literal.init();
};
+ const is_pub = toplevel and !is_unnamed;
const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
payload.* = .{
.base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
.data = .{
+ .init = enum_type_node,
.name = name,
- .init = init_node,
},
};
@@ -1193,18 +1169,6 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E
} else {
try scope.appendNode(Node.initPayload(&payload.base));
}
-
- for (redecls.items) |redecl| {
- if (toplevel) {
- try addTopLevelDecl(c, redecl.field_name, try Tag.pub_enum_redecl.create(c.arena, redecl));
- } else {
- try scope.appendNode(try Tag.enum_redecl.create(c.arena, .{
- .enum_val_name = try bs.makeMangledName(c, redecl.enum_val_name),
- .field_name = redecl.field_name,
- .enum_name = redecl.enum_name,
- }));
- }
- }
}
const ResultUsed = enum {
@@ -2098,8 +2062,7 @@ fn finishBoolExpr(
},
.Enum => {
// node != 0
- const int_val = try Tag.enum_to_int.create(c.arena, node);
- return Tag.not_equal.create(c.arena, .{ .lhs = int_val, .rhs = Tag.zero_literal.init() });
+ return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.zero_literal.init() });
},
.Elaborated => {
const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);
@@ -2312,21 +2275,22 @@ fn transCCast(
if (dst_type.eq(src_type)) return expr;
if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))
return transCPtrCast(c, scope, loc, dst_type, src_type, expr);
+ if (cIsEnum(dst_type)) return transCCast(c, scope, loc, cIntTypeForEnum(dst_type), src_type, expr);
+ if (cIsEnum(src_type)) return transCCast(c, scope, loc, dst_type, cIntTypeForEnum(src_type), expr);
const dst_node = try transQualType(c, scope, dst_type, loc);
- if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) {
+ if (cIsInteger(dst_type) and cIsInteger(src_type)) {
// 1. If src_type is an enum, determine the underlying signed int type
// 2. Extend or truncate without changing signed-ness.
// 3. Bit-cast to correct signed-ness
- const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);
- const src_type_is_signed = cIsSignedInteger(src_int_type);
- var src_int_expr = if (cIsInteger(src_type)) expr else try Tag.enum_to_int.create(c.arena, expr);
+ const src_type_is_signed = cIsSignedInteger(src_type);
+ var src_int_expr = expr;
if (isBoolRes(src_int_expr)) {
src_int_expr = try Tag.bool_to_int.create(c.arena, src_int_expr);
}
- switch (cIntTypeCmp(dst_type, src_int_type)) {
+ switch (cIntTypeCmp(dst_type, src_type)) {
.lt => {
// @truncate(SameSignSmallerInt, src_int_expr)
const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);
@@ -2379,14 +2343,6 @@ fn transCCast(
const bool_to_int = try Tag.bool_to_int.create(c.arena, expr);
return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int });
}
- if (cIsEnum(dst_type)) {
- // import("std").meta.cast(dest_type, val)
- return Tag.helpers_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
- }
- if (cIsEnum(src_type) and !cIsEnum(dst_type)) {
- // @enumToInt(val)
- return Tag.enum_to_int.create(c.arena, expr);
- }
// @as(dest_type, val)
return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
}
@@ -5975,7 +5931,6 @@ fn getContainer(c: *Context, node: Node) ?Node {
switch (node.tag()) {
.@"union",
.@"struct",
- .@"enum",
.address_of,
.bit_not,
.not,
src/zig_clang.cpp
@@ -3228,12 +3228,6 @@ bool ZigClangEnumDecl_enumerator_iterator_neq(
return casted_a != casted_b;
}
-const struct ZigClangExpr *ZigClangEnumConstantDecl_getInitExpr(const struct ZigClangEnumConstantDecl *self) {
- auto casted = reinterpret_cast<const clang::EnumConstantDecl *>(self);
- const clang::Expr *result = casted->getInitExpr();
- return reinterpret_cast<const ZigClangExpr *>(result);
-}
-
const struct ZigClangAPSInt *ZigClangEnumConstantDecl_getInitVal(const struct ZigClangEnumConstantDecl *self) {
auto casted = reinterpret_cast<const clang::EnumConstantDecl *>(self);
const llvm::APSInt *result = &casted->getInitVal();
src/zig_clang.h
@@ -1326,6 +1326,5 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFieldDecl_getLocation(const s
ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangFieldDecl_getParent(const struct ZigClangFieldDecl *);
ZIG_EXTERN_C unsigned ZigClangFieldDecl_getFieldIndex(const struct ZigClangFieldDecl *);
-ZIG_EXTERN_C const struct ZigClangExpr *ZigClangEnumConstantDecl_getInitExpr(const struct ZigClangEnumConstantDecl *);
ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangEnumConstantDecl_getInitVal(const struct ZigClangEnumConstantDecl *);
#endif
test/run_translated_c.zig
@@ -1598,4 +1598,53 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
+
+ cases.add("Enum constants are assigned correct type. Issue #9153",
+ \\enum A { A0, A1=0xFFFFFFFF };
+ \\enum B { B0=-1, B1=0xFFFFFFFF };
+ \\enum C { C0=-1, C1=0 };
+ \\enum D { D0, D1=0xFFFFFFFFFFL };
+ \\enum E { E0=-1, E1=0xFFFFFFFFFFL };
+ \\int main(void) {
+ \\ signed char a0 = A0, a1 = A1;
+ \\ signed char b0 = B0, b1 = B1;
+ \\ signed char c0 = C0, c1 = C1;
+ \\ signed char d0 = D0, d1 = D1;
+ \\ signed char e0 = E0, e1 = E1;
+ \\ return 0;
+ \\}
+ , "");
+
+ cases.add("Enum constant matches enum name; multiple enumerations with same value",
+ \\#include <stdlib.h>
+ \\enum FOO {
+ \\ FOO = 1,
+ \\ BAR = 2,
+ \\ BAZ = 1,
+ \\};
+ \\int main(void) {
+ \\ enum FOO x = BAZ;
+ \\ if (x != 1) abort();
+ \\ if (x != BAZ) abort();
+ \\ if (x != FOO) abort();
+ \\}
+ , "");
+
+ cases.add("Scoped enums",
+ \\#include <stdlib.h>
+ \\int main(void) {
+ \\ enum Foo { A, B, C };
+ \\ enum Foo a = B;
+ \\ if (a != B) abort();
+ \\ if (a != 1) abort();
+ \\ {
+ \\ enum Foo { A = 5, B = 6, C = 7 };
+ \\ enum Foo a = B;
+ \\ if (a != B) abort();
+ \\ if (a != 6) abort();
+ \\ }
+ \\ if (a != B) abort();
+ \\ if (a != 1) abort();
+ \\}
+ , "");
}
test/translate_c.zig
@@ -30,15 +30,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ int a, b;
\\} Bar;
, &[_][]const u8{
- \\pub const Foo = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ A,
- \\ B,
- \\ _,
- \\};
- \\pub const FooA = @enumToInt(Foo.A);
- \\pub const FooB = @enumToInt(Foo.B);
+ \\pub const FooA: c_int = 0;
+ \\pub const FooB: c_int = 1;
+ \\pub const Foo =
+ ++ " " ++ default_enum_type ++
+ \\;
\\pub const Bar = extern struct {
\\ a: c_int,
\\ b: c_int,
@@ -103,54 +99,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const PTR = ?*c_void;
});
- cases.add("scoped enum",
- \\void foo() {
- \\ enum Foo {
- \\ A,
- \\ B,
- \\ C,
- \\ };
- \\ enum Foo a = B;
- \\ {
- \\ enum Foo {
- \\ A,
- \\ B,
- \\ C,
- \\ };
- \\ enum Foo a = B;
- \\ }
- \\}
- , &[_][]const u8{
- \\pub export fn foo() void {
- \\ const enum_Foo = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ A,
- \\ B,
- \\ C,
- \\ _,
- \\ };
- \\ const A = @enumToInt(enum_Foo.A);
- \\ const B = @enumToInt(enum_Foo.B);
- \\ const C = @enumToInt(enum_Foo.C);
- \\ var a: enum_Foo = @import("std").zig.c_translation.cast(enum_Foo, B);
- \\ {
- \\ const enum_Foo = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ A,
- \\ B,
- \\ C,
- \\ _,
- \\ };
- \\ const A_2 = @enumToInt(enum_Foo.A);
- \\ const B_3 = @enumToInt(enum_Foo.B);
- \\ const C_4 = @enumToInt(enum_Foo.C);
- \\ var a_5: enum_Foo = @import("std").zig.c_translation.cast(enum_Foo, B_3);
- \\ }
- \\}
- });
-
cases.add("scoped record",
\\void foo() {
\\ struct Foo {
@@ -1208,32 +1156,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ VAL23 = 0xFFFFFFFFFFFFFFFF,
\\};
, &[_][]const u8{
- \\pub const enum_EnumWithInits = extern enum(c_longlong) {
- \\ VAL01 = 0,
- \\ VAL02 = 1,
- \\ VAL03 = 2,
- \\ VAL04 = 3,
- \\ VAL05 = -1,
- \\ VAL06 = -2,
- \\ VAL07 = -3,
- \\ VAL08 = -4,
- \\ VAL09 = -3,
- \\ VAL10 = -1000012000,
- \\ VAL11 = -1000161000,
- \\ VAL12 = -1000174001,
- \\ VAL13 = -3,
- \\ VAL14 = -1000012000,
- \\ VAL15 = -1000161000,
- \\ VAL16 = -3,
- \\ VAL17 = 1000011998,
- \\ VAL18 = 1152921504606846976,
- \\ VAL19 = 3458764513820540927,
- \\ VAL20 = 6917529027641081854,
- \\ VAL21 = 6917529027641081853,
- \\ VAL22 = 0,
- \\ VAL23 = -1,
- \\ _,
- \\};
+ \\pub const VAL01: c_int = 0;
+ \\pub const VAL02: c_int = 1;
+ \\pub const VAL03: c_int = 2;
+ \\pub const VAL04: c_int = 3;
+ \\pub const VAL05: c_int = -1;
+ \\pub const VAL06: c_int = -2;
+ \\pub const VAL07: c_int = -3;
+ \\pub const VAL08: c_int = -4;
+ \\pub const VAL09: c_int = -3;
+ \\pub const VAL10: c_int = -1000012000;
+ \\pub const VAL11: c_int = -1000161000;
+ \\pub const VAL12: c_int = -1000174001;
+ \\pub const VAL13: c_int = -3;
+ \\pub const VAL14: c_int = -1000012000;
+ \\pub const VAL15: c_int = -1000161000;
+ \\pub const VAL16: c_int = -3;
+ \\pub const VAL17: c_int = 1000011998;
+ \\pub const VAL18: c_longlong = 1152921504606846976;
+ \\pub const VAL19: c_longlong = 3458764513820540927;
+ \\pub const VAL20: c_longlong = 6917529027641081854;
+ \\pub const VAL21: c_longlong = 6917529027641081853;
+ \\pub const VAL22: c_int = 0;
+ \\pub const VAL23: c_longlong = -1;
+ \\pub const enum_EnumWithInits = c_longlong;
});
}
@@ -1591,11 +1537,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\extern enum enum_ty my_enum;
\\enum enum_ty { FOO };
, &[_][]const u8{
- \\pub const enum_enum_ty = extern enum(c_int) {
- \\ FOO,
- \\ _,
- \\};
- \\pub const FOO = @enumToInt(enum_enum_ty.FOO);
+ \\pub const FOO: c_int = 0;
+ \\pub const enum_enum_ty = c_int;
\\pub extern var my_enum: enum_enum_ty;
});
@@ -1716,57 +1659,37 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ p,
\\};
, &[_][]const u8{
- \\pub const d = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ a,
- \\ b,
- \\ c,
- \\ _,
- \\};
- \\pub const a = @enumToInt(d.a);
- \\pub const b = @enumToInt(d.b);
- \\pub const c = @enumToInt(d.c);
- \\const enum_unnamed_1 = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ e = 0,
- \\ f = 4,
- \\ g = 5,
- \\ _,
- \\};
- \\pub const e = @enumToInt(enum_unnamed_1.e);
- \\pub const f = @enumToInt(enum_unnamed_1.f);
- \\pub const g = @enumToInt(enum_unnamed_1.g);
- \\pub export var h: enum_unnamed_1 = @import("std").zig.c_translation.cast(enum_unnamed_1, e);
- \\const enum_unnamed_2 = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ i,
- \\ j,
- \\ k,
- \\ _,
- \\};
- \\pub const i = @enumToInt(enum_unnamed_2.i);
- \\pub const j = @enumToInt(enum_unnamed_2.j);
- \\pub const k = @enumToInt(enum_unnamed_2.k);
+ \\pub const a: c_int = 0;
+ \\pub const b: c_int = 1;
+ \\pub const c: c_int = 2;
+ \\pub const d =
+ ++ " " ++ default_enum_type ++
+ \\;
+ \\pub const e: c_int = 0;
+ \\pub const f: c_int = 4;
+ \\pub const g: c_int = 5;
+ \\const enum_unnamed_1 =
+ ++ " " ++ default_enum_type ++
+ \\;
+ \\pub export var h: enum_unnamed_1 = @bitCast(c_uint, e);
+ \\pub const i: c_int = 0;
+ \\pub const j: c_int = 1;
+ \\pub const k: c_int = 2;
+ \\const enum_unnamed_2 =
+ ++ " " ++ default_enum_type ++
+ \\;
\\pub const struct_Baz = extern struct {
\\ l: enum_unnamed_2,
\\ m: d,
\\};
- \\pub const enum_i = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ n,
- \\ o,
- \\ p,
- \\ _,
- \\};
- \\pub const n = @enumToInt(enum_i.n);
- \\pub const o = @enumToInt(enum_i.o);
- \\pub const p = @enumToInt(enum_i.p);
+ \\pub const n: c_int = 0;
+ \\pub const o: c_int = 1;
+ \\pub const p: c_int = 2;
+ \\pub const enum_i =
+ ++ " " ++ default_enum_type ++
+ \\;
,
- \\pub const Baz = struct_Baz;
+ "pub const Baz = struct_Baz;",
});
cases.add("#define a char literal",
@@ -2257,15 +2180,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ Two,
\\};
, &[_][]const u8{
- \\const enum_unnamed_1 = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ One,
- \\ Two,
- \\ _,
- \\};
- \\pub const One = @enumToInt(enum_unnamed_1.One);
- \\pub const Two = @enumToInt(enum_unnamed_1.Two);
+ \\pub const One: c_int = 0;
+ \\pub const Two: c_int = 1;
+ \\const enum_unnamed_1 =
+ ++ " " ++ default_enum_type ++
+ \\;
});
cases.add("c style cast",
@@ -2363,32 +2282,27 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
\\}
, &[_][]const u8{
- \\pub const enum_Foo = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ A,
- \\ B,
- \\ C,
- \\ _,
- \\};
- \\pub const FooA = @enumToInt(enum_Foo.A);
- \\pub const FooB = @enumToInt(enum_Foo.B);
- \\pub const FooC = @enumToInt(enum_Foo.C);
+ \\pub const FooA: c_int = 0;
+ \\pub const FooB: c_int = 1;
+ \\pub const FooC: c_int = 2;
+ \\pub const enum_Foo =
+ ++ " " ++ default_enum_type ++
+ \\;
\\pub const SomeTypedef = c_int;
\\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
\\ var a = arg_a;
\\ var b = arg_b;
\\ var c = arg_c;
- \\ var d: enum_Foo = @import("std").zig.c_translation.cast(enum_Foo, FooA);
+ \\ var d: enum_Foo = @bitCast(c_uint, FooA);
\\ var e: c_int = @boolToInt((a != 0) and (b != 0));
\\ var f: c_int = @boolToInt((b != 0) and (c != null));
\\ var g: c_int = @boolToInt((a != 0) and (c != null));
\\ var h: c_int = @boolToInt((a != 0) or (b != 0));
\\ var i: c_int = @boolToInt((b != 0) or (c != null));
\\ var j: c_int = @boolToInt((a != 0) or (c != null));
- \\ var k: c_int = @boolToInt((a != 0) or (@bitCast(c_int, @enumToInt(d)) != 0));
- \\ var l: c_int = @boolToInt((@bitCast(c_int, @enumToInt(d)) != 0) and (b != 0));
- \\ var m: c_int = @boolToInt((c != null) or (@bitCast(c_uint, @enumToInt(d)) != 0));
+ \\ var k: c_int = @boolToInt((a != 0) or (@bitCast(c_int, d) != 0));
+ \\ var l: c_int = @boolToInt((@bitCast(c_int, d) != 0) and (b != 0));
+ \\ var m: c_int = @boolToInt((c != null) or (d != 0));
\\ var td: SomeTypedef = 44;
\\ var o: c_int = @boolToInt((td != 0) or (b != 0));
\\ var p: c_int = @boolToInt((c != null) and (td != 0));
@@ -2413,16 +2327,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ x: c_int,
\\ y: c_int,
\\};
- ,
- \\pub const enum_Bar = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ A,
- \\ B,
- \\ _,
- \\};
- \\pub const BarA = @enumToInt(enum_Bar.A);
- \\pub const BarB = @enumToInt(enum_Bar.B);
+ \\pub const BarA: c_int = 0;
+ \\pub const BarB: c_int = 1;
+ \\pub const enum_Bar =
+ ++ " " ++ default_enum_type ++
+ \\;
\\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
,
\\pub const Foo = struct_Foo;
@@ -2693,17 +2602,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return 4;
\\}
, &[_][]const u8{
- \\pub const enum_SomeEnum = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ A,
- \\ B,
- \\ C,
- \\ _,
- \\};
- \\pub const A = @enumToInt(enum_SomeEnum.A);
- \\pub const B = @enumToInt(enum_SomeEnum.B);
- \\pub const C = @enumToInt(enum_SomeEnum.C);
+ \\pub const A: c_int = 0;
+ \\pub const B: c_int = 1;
+ \\pub const C: c_int = 2;
+ \\pub const enum_SomeEnum =
+ ++ " " ++ default_enum_type ++
+ \\;
\\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
\\ var a = arg_a;
\\ var b = arg_b;
@@ -2712,7 +2616,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ if (a != 0) return 0;
\\ if (b != 0) return 1;
\\ if (c != null) return 2;
- \\ if (@enumToInt(d) != 0) return 3;
+ \\ if (d != 0) return 3;
\\ return 4;
\\}
});
@@ -3161,17 +3065,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ Foo1,
\\};
, &[_][]const u8{
- \\pub const enum_Foo = extern enum(
- ++ default_enum_type ++
- \\) {
- \\ A = 2,
- \\ B = 5,
- \\ @"1" = 6,
- \\ _,
- \\};
- \\pub const FooA = @enumToInt(enum_Foo.A);
- \\pub const FooB = @enumToInt(enum_Foo.B);
- \\pub const Foo1 = @enumToInt(enum_Foo.@"1");
+ \\pub const FooA: c_int = 2;
+ \\pub const FooB: c_int = 5;
+ \\pub const Foo1: c_int = 6;
+ \\pub const enum_Foo =
+ ++ " " ++ default_enum_type ++
+ \\;
,
\\pub const Foo = enum_Foo;
});