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