| ... | @@ -1049,21 +1049,33 @@ fn buildFlexibleArrayFn( | ... | @@ -1049,21 +1049,33 @@ fn buildFlexibleArrayFn( |
| 1049 | return Node.initPayload(&payload.base); | 1049 | return Node.initPayload(&payload.base); |
| 1050 | } | 1050 | } |
| 1051 | | 1051 | |
| | 1052 | /// Return true if `field_decl` is the flexible array field for its parent record |
| 1052 | fn isFlexibleArrayFieldDecl(c: *Context, field_decl: *const clang.FieldDecl) bool { | 1053 | fn isFlexibleArrayFieldDecl(c: *Context, field_decl: *const clang.FieldDecl) bool { |
| 1053 | return qualTypeCanon(field_decl.getType()).isIncompleteOrZeroLengthArrayType(c.clang_context); | 1054 | const record_decl = field_decl.getParent() orelse return false; |
| | 1055 | const record_flexible_field = flexibleArrayField(c, record_decl) orelse return false; |
| | 1056 | return field_decl == record_flexible_field; |
| 1054 | } | 1057 | } |
| 1055 | | 1058 | |
| | 1059 | /// Find the flexible array field for a record if any. A flexible array field is an |
| | 1060 | /// incomplete or zero-length array that occurs as the last field of a record. |
| 1056 | /// clang's RecordDecl::hasFlexibleArrayMember is not suitable for determining | 1061 | /// clang's RecordDecl::hasFlexibleArrayMember is not suitable for determining |
| 1057 | /// this because it returns false for a record that ends with a zero-length | 1062 | /// this because it returns false for a record that ends with a zero-length |
| 1058 | /// array, but we consider those to be flexible arrays | 1063 | /// array, but we consider those to be flexible arrays |
| 1059 | fn hasFlexibleArrayField(c: *Context, record_def: *const clang.RecordDecl) bool { | 1064 | fn flexibleArrayField(c: *Context, record_def: *const clang.RecordDecl) ?*const clang.FieldDecl { |
| 1060 | var it = record_def.field_begin(); | 1065 | var it = record_def.field_begin(); |
| 1061 | const end_it = record_def.field_end(); | 1066 | const end_it = record_def.field_end(); |
| | 1067 | var flexible_field: ?*const clang.FieldDecl = null; |
| 1062 | while (it.neq(end_it)) : (it = it.next()) { | 1068 | while (it.neq(end_it)) : (it = it.next()) { |
| 1063 | const field_decl = it.deref(); | 1069 | const field_decl = it.deref(); |
| 1064 | if (isFlexibleArrayFieldDecl(c, field_decl)) return true; | 1070 | const ty = qualTypeCanon(field_decl.getType()); |
| | 1071 | const incomplete_or_zero_size = ty.isIncompleteOrZeroLengthArrayType(c.clang_context); |
| | 1072 | if (incomplete_or_zero_size) { |
| | 1073 | flexible_field = field_decl; |
| | 1074 | } else { |
| | 1075 | flexible_field = null; |
| | 1076 | } |
| 1065 | } | 1077 | } |
| 1066 | return false; | 1078 | return flexible_field; |
| 1067 | } | 1079 | } |
| 1068 | | 1080 | |
| 1069 | fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordDecl) Error!void { | 1081 | fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordDecl) Error!void { |
| ... | @@ -1117,7 +1129,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD | ... | @@ -1117,7 +1129,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD |
| 1117 | var functions = std.ArrayList(Node).init(c.gpa); | 1129 | var functions = std.ArrayList(Node).init(c.gpa); |
| 1118 | defer functions.deinit(); | 1130 | defer functions.deinit(); |
| 1119 | | 1131 | |
| 1120 | const has_flexible_array = hasFlexibleArrayField(c, record_def); | 1132 | const flexible_field = flexibleArrayField(c, record_def); |
| 1121 | var unnamed_field_count: u32 = 0; | 1133 | var unnamed_field_count: u32 = 0; |
| 1122 | var it = record_def.field_begin(); | 1134 | var it = record_def.field_begin(); |
| 1123 | const end_it = record_def.field_end(); | 1135 | const end_it = record_def.field_end(); |
| ... | @@ -1143,7 +1155,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD | ... | @@ -1143,7 +1155,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD |
| 1143 | unnamed_field_count += 1; | 1155 | unnamed_field_count += 1; |
| 1144 | is_anon = true; | 1156 | is_anon = true; |
| 1145 | } | 1157 | } |
| 1146 | if (isFlexibleArrayFieldDecl(c, field_decl)) { | 1158 | if (flexible_field == field_decl) { |
| 1147 | const flexible_array_fn = buildFlexibleArrayFn(c, scope, layout, field_name, field_decl) catch |err| switch (err) { | 1159 | const flexible_array_fn = buildFlexibleArrayFn(c, scope, layout, field_name, field_decl) catch |err| switch (err) { |
| 1148 | error.UnsupportedType => { | 1160 | error.UnsupportedType => { |
| 1149 | try c.opaque_demotes.put(c.gpa, @intFromPtr(record_decl.getCanonicalDecl()), {}); | 1161 | try c.opaque_demotes.put(c.gpa, @intFromPtr(record_decl.getCanonicalDecl()), {}); |
| ... | @@ -1164,7 +1176,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD | ... | @@ -1164,7 +1176,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD |
| 1164 | else => |e| return e, | 1176 | else => |e| return e, |
| 1165 | }; | 1177 | }; |
| 1166 | | 1178 | |
| 1167 | const alignment = if (has_flexible_array and field_decl.getFieldIndex() == 0) | 1179 | const alignment = if (flexible_field != null and field_decl.getFieldIndex() == 0) |
| 1168 | @as(c_uint, @intCast(record_alignment)) | 1180 | @as(c_uint, @intCast(record_alignment)) |
| 1169 | else | 1181 | else |
| 1170 | ClangAlignment.forField(c, field_decl, record_def).zigAlignment(); | 1182 | ClangAlignment.forField(c, field_decl, record_def).zigAlignment(); |