| ... | ... | @@ -1049,21 +1049,33 @@ fn buildFlexibleArrayFn( |
| 1049 | 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 | 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 | 1061 | /// clang's RecordDecl::hasFlexibleArrayMember is not suitable for determining |
| 1057 | 1062 | /// this because it returns false for a record that ends with a zero-length |
| 1058 | 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 | 1065 | var it = record_def.field_begin(); |
| 1061 | 1066 | const end_it = record_def.field_end(); |
| 1067 | var flexible_field: ?*const clang.FieldDecl = null; |
| 1062 | 1068 | while (it.neq(end_it)) : (it = it.next()) { |
| 1063 | 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 | 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 | 1129 | var functions = std.ArrayList(Node).init(c.gpa); |
| 1118 | 1130 | defer functions.deinit(); |
| 1119 | 1131 | |
| 1120 | | const has_flexible_array = hasFlexibleArrayField(c, record_def); |
| 1132 | const flexible_field = flexibleArrayField(c, record_def); |
| 1121 | 1133 | var unnamed_field_count: u32 = 0; |
| 1122 | 1134 | var it = record_def.field_begin(); |
| 1123 | 1135 | const end_it = record_def.field_end(); |
| ... | ... | @@ -1143,7 +1155,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD |
| 1143 | 1155 | unnamed_field_count += 1; |
| 1144 | 1156 | is_anon = true; |
| 1145 | 1157 | } |
| 1146 | | if (isFlexibleArrayFieldDecl(c, field_decl)) { |
| 1158 | if (flexible_field == field_decl) { |
| 1147 | 1159 | const flexible_array_fn = buildFlexibleArrayFn(c, scope, layout, field_name, field_decl) catch |err| switch (err) { |
| 1148 | 1160 | error.UnsupportedType => { |
| 1149 | 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 | 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 | 1180 | @as(c_uint, @intCast(record_alignment)) |
| 1169 | 1181 | else |
| 1170 | 1182 | ClangAlignment.forField(c, field_decl, record_def).zigAlignment(); |