From ee651c3cd358f40f60db0bbcd82ffde99aed9b88 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 29 May 2022 12:04:50 +0300 Subject: [PATCH] Revert "reserve correct space for bitfields" This reverts commit 22cb6938891c73d64b749a2516c8eaf79aa25b03. --- src/clang.zig | 6 ---- src/translate_c.zig | 65 +++++--------------------------------------- src/zig_clang.cpp | 12 -------- src/zig_clang.h | 2 -- test/translate_c.zig | 54 +++++++++++++++++++++++------------- 5 files changed, 42 insertions(+), 97 deletions(-) diff --git a/src/clang.zig b/src/clang.zig index 769021fc44..64c7da5091 100644 --- a/src/clang.zig +++ b/src/clang.zig @@ -476,12 +476,6 @@ pub const FieldDecl = opaque { pub const isBitField = ZigClangFieldDecl_isBitField; extern fn ZigClangFieldDecl_isBitField(*const FieldDecl) bool; - pub const getBitWidthValue = ZigClangFieldDecl_getBitWidthValue; - extern fn ZigClangFieldDecl_getBitWidthValue(*const FieldDecl, *const ASTContext) c_uint; - - pub const isZeroLengthBitField = ZigClangFieldDecl_isZeroLengthBitField; - extern fn ZigClangFieldDecl_isZeroLengthBitField(*const FieldDecl, *const ASTContext) bool; - pub const getType = ZigClangFieldDecl_getType; extern fn ZigClangFieldDecl_getType(*const FieldDecl) QualType; diff --git a/src/translate_c.zig b/src/translate_c.zig index 874dbf0521..8c4bd5e9bf 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -1085,15 +1085,17 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD const layout = record_def.getASTRecordLayout(c.clang_context); const record_alignment = layout.getAlignment(); - var record_bitfield_count: u32 = 0; - var bits_unused: i32 = 0; - var bits_type: clang.BuiltinTypeKind = clang.BuiltinTypeKind.Void; - while (it.neq(end_it)) : (it = it.next()) { const field_decl = it.deref(); const field_loc = field_decl.getLocation(); const field_qt = field_decl.getType(); + if (field_decl.isBitField()) { + try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {}); + try warn(c, scope, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name}); + break :blk Tag.opaque_literal.init(); + } + var is_anon = false; var field_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin()); if (field_decl.isAnonymousStructOrUnion() or field_name.len == 0) { @@ -1123,53 +1125,6 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD else => |e| return e, }; - if (field_decl.isBitField()) { - var this_field_width = @intCast(i32, field_decl.getBitWidthValue(c.clang_context)); - - // are we starting new bitfield? - if (bits_unused <= 0) { - const size_map = std.ComptimeStringMap(u16, .{ .{ "u8", 8 }, .{ "c_ushort", 16 }, .{ "u16", 16 }, .{ "u32", 32 }, .{ "c_uint", 32 }, .{ "c_ulong", 32 }, .{ "c_ulonglong", 64 }, .{ "u64", 64 } }); - - bits_type = @ptrCast(*const clang.BuiltinType, field_qt.getTypePtr()).getKind(); - - var field_width = field_type.castTag(.type).?.*.data; // we just set it 10 lines back. this should not fail. - - if (size_map.get(field_width)) |sz| { - bits_unused = @intCast(i32, sz) - this_field_width; - field_name = try std.fmt.allocPrint(c.arena, "bitfield{d}", .{record_bitfield_count}); - record_bitfield_count += 1; - } else { - try warn(c, scope, field_loc, "{s} demoted to opaque type - bitfield type not unsigned or unknown. type:{s} ", .{ container_kind_name, field_width }); - break :blk Tag.opaque_literal.init(); - } - } else { - var this_type = @ptrCast(*const clang.BuiltinType, field_qt.getTypePtr()).getKind(); - if (field_decl.isZeroLengthBitField(c.clang_context)) { - try warn(c, scope, field_loc, "{s} demoted to opaque type - bitfield with zero size not supported", .{container_kind_name}); - break :blk Tag.opaque_literal.init(); - } else if (bits_type != this_type) { - try warn(c, scope, field_loc, "{s} demoted to opaque type - bitfield type changed in the middle of bitfield was;{s} is:{s}", .{ container_kind_name, @tagName(bits_type), @tagName(this_type) }); - break :blk Tag.opaque_literal.init(); - } else { - // next - bits_unused -= this_field_width; - if (bits_unused < 0) { - try warn(c, scope, field_loc, "{s} demoted to opaque type - bitfield overrun type size not supported", .{container_kind_name}); - break :blk Tag.opaque_literal.init(); - } - } - continue; // free the field_type? tag is alloc'd - } - } else { - if (bits_unused >= 8) { - // if they didn't add a "reserved:n" at the end, and the # of bits used is more than 1 byte of their requested size, - // the layout is to compiler specific. - try warn(c, scope, field_loc, "{s} demoted to opaque type - less bits used than field size. unused bit count:{d}", .{ container_kind_name, bits_unused }); - break :blk Tag.opaque_literal.init(); - } - bits_unused = 0; - } - const alignment = if (has_flexible_array and field_decl.getFieldIndex() == 0) @intCast(c_uint, record_alignment) else @@ -1185,10 +1140,6 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD .alignment = alignment, }); } - if (bits_unused >= 8) { // one last check if the last field was a bitfield - try warn(c, scope, record_loc, "{s} demoted to opaque type - less bits used than field size. unused bit count:{d}", .{ container_kind_name, bits_unused }); - break :blk Tag.opaque_literal.init(); - } const record_payload = try c.arena.create(ast.Payload.Record); record_payload.* = .{ @@ -2625,9 +2576,7 @@ fn transInitListExprRecord( continue; } - if (init_i >= init_count) { - return fail(c, error.UnsupportedTranslation, loc, "init list longer fields in record. Record has bitfield?", .{}); - } + assert(init_i < init_count); const elem_expr = expr.getInit(init_i); init_i += 1; diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 0ceffe4c3d..ea3f09c8d5 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -3335,18 +3335,6 @@ bool ZigClangFieldDecl_isBitField(const struct ZigClangFieldDecl *self) { return casted->isBitField(); } -unsigned ZigClangFieldDecl_getBitWidthValue( const struct ZigClangFieldDecl *self, const ZigClangASTContext *ctx) { - auto casted = reinterpret_cast(self); - auto casted_ctx = const_cast(reinterpret_cast(ctx)); - return casted->getBitWidthValue(*casted_ctx); -} - -bool ZigClangFieldDecl_isZeroLengthBitField( ZigClangFieldDecl *self, const ZigClangASTContext *ctx) { - auto casted = reinterpret_cast(self); - auto casted_ctx = const_cast(reinterpret_cast(ctx)); - return casted->isZeroLengthBitField(*casted_ctx); -} - bool ZigClangFieldDecl_isAnonymousStructOrUnion(const ZigClangFieldDecl *field_decl) { return reinterpret_cast(field_decl)->isAnonymousStructOrUnion(); } diff --git a/src/zig_clang.h b/src/zig_clang.h index 0b6d97e07e..267edfaea8 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -1407,8 +1407,6 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangMacroDefinitionRecord_getSour ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangMacroDefinitionRecord_getSourceRange_getEnd(const struct ZigClangMacroDefinitionRecord *); ZIG_EXTERN_C bool ZigClangFieldDecl_isBitField(const struct ZigClangFieldDecl *); -ZIG_EXTERN_C unsigned ZigClangFieldDecl_getBitWidthValue( const struct ZigClangFieldDecl *, const ZigClangASTContext *); -ZIG_EXTERN_C bool ZigClangFieldDecl_isZeroLengthBitField( ZigClangFieldDecl *, const ZigClangASTContext *); ZIG_EXTERN_C bool ZigClangFieldDecl_isAnonymousStructOrUnion(const ZigClangFieldDecl *); ZIG_EXTERN_C struct ZigClangQualType ZigClangFieldDecl_getType(const struct ZigClangFieldDecl *); ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFieldDecl_getLocation(const struct ZigClangFieldDecl *); diff --git a/test/translate_c.zig b/test/translate_c.zig index 14b5783fef..c49aa55baa 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -915,6 +915,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\}; }); + cases.add("pointer to struct demoted to opaque due to bit fields", + \\struct Foo { + \\ unsigned int: 1; + \\}; + \\struct Bar { + \\ struct Foo *foo; + \\}; + , &[_][]const u8{ + \\pub const struct_Foo = opaque {}; + , + \\pub const struct_Bar = extern struct { + \\ foo: ?*struct_Foo, + \\}; + }); + cases.add("macro with left shift", \\#define REDISMODULE_READ (1<<0) , &[_][]const u8{ @@ -3562,33 +3577,34 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("function that dereferences bitfield works", + cases.add("Demote function that initializes opaque struct", + \\struct my_struct { + \\ unsigned a: 15; + \\ unsigned: 2; + \\ unsigned b: 15; + \\}; + \\void initialize(void) { + \\ struct my_struct S = {.a = 1, .b = 2}; + \\} + , &[_][]const u8{ + \\warning: cannot initialize opaque type + , + \\warning: unable to translate function, demoted to extern + \\pub extern fn initialize() void; + }); + + cases.add("Demote function that dereferences opaque type", \\struct my_struct { \\ unsigned a: 1; - \\ unsigned b: 28; \\}; \\void deref(struct my_struct *s) { \\ *s; \\} , &[_][]const u8{ - \\pub const struct_my_struct = extern struct { - \\ bitfield0: c_uint, + \\warning: cannot dereference opaque type , - \\pub export fn deref(arg_s: ?*struct_my_struct) void { - \\ var s = arg_s; - \\ _ = s.*; - \\} - }); - - cases.add("bitfield don't cover requedted space", - \\struct inner { - \\ unsigned a: 1; - \\ char after; - \\}; - , &[_][]const u8{ - \\less bits used than field size. - , - \\pub const struct_inner = opaque {}; + \\warning: unable to translate function, demoted to extern + \\pub extern fn deref(arg_s: ?*struct_my_struct) void; }); cases.add("Function prototype declared within function",