diff --git a/src/Parser.zig b/src/Parser.zig index 422c655c..4fd465b8 100644 --- a/src/Parser.zig +++ b/src/Parser.zig @@ -3356,8 +3356,8 @@ fn initializerItem(p: *Parser, il: *InitList, init_ty: Type) Error!bool { excess: { if (index_hint) |*hint| { - if (try p.findScalarInitializerAt(&cur_il, &cur_ty, res.ty, first_tok, hint)) break :excess; - } else if (try p.findScalarInitializer(&cur_il, &cur_ty, res.ty, first_tok)) break :excess; + if (try p.findScalarInitializerAt(&cur_il, &cur_ty, &res, first_tok, hint)) break :excess; + } else if (try p.findScalarInitializer(&cur_il, &cur_ty, &res, first_tok)) break :excess; if (designation) break :excess; if (!warned_excess) try p.errTok(if (init_ty.isArray()) .excess_array_init else .excess_struct_init, first_tok); @@ -3407,7 +3407,7 @@ fn initializerItem(p: *Parser, il: *InitList, init_ty: Type) Error!bool { } /// Returns true if the value is unused. -fn findScalarInitializerAt(p: *Parser, il: **InitList, ty: *Type, actual_ty: Type, first_tok: TokenIndex, start_index: *u64) Error!bool { +fn findScalarInitializerAt(p: *Parser, il: **InitList, ty: *Type, res: *Result, first_tok: TokenIndex, start_index: *u64) Error!bool { if (ty.isArray()) { if (il.*.node != .none) return false; start_index.* += 1; @@ -3423,7 +3423,7 @@ fn findScalarInitializerAt(p: *Parser, il: **InitList, ty: *Type, actual_ty: Typ if (start_index.* < elem_count) { ty.* = elem_ty; il.* = try arr_il.find(p.gpa, start_index.*); - _ = try p.findScalarInitializer(il, ty, actual_ty, first_tok); + _ = try p.findScalarInitializer(il, ty, res, first_tok); return true; } return false; @@ -3441,7 +3441,7 @@ fn findScalarInitializerAt(p: *Parser, il: **InitList, ty: *Type, actual_ty: Typ const field = fields[@intCast(start_index.*)]; ty.* = field.ty; il.* = try struct_il.find(p.gpa, start_index.*); - _ = try p.findScalarInitializer(il, ty, actual_ty, first_tok); + _ = try p.findScalarInitializer(il, ty, res, first_tok); return true; } return false; @@ -3452,7 +3452,8 @@ fn findScalarInitializerAt(p: *Parser, il: **InitList, ty: *Type, actual_ty: Typ } /// Returns true if the value is unused. -fn findScalarInitializer(p: *Parser, il: **InitList, ty: *Type, actual_ty: Type, first_tok: TokenIndex) Error!bool { +fn findScalarInitializer(p: *Parser, il: **InitList, ty: *Type, res: *Result, first_tok: TokenIndex) Error!bool { + const actual_ty = res.ty; if (ty.isArray() or ty.isComplex()) { if (il.*.node != .none) return false; const start_index = il.*.list.items.len; @@ -3470,7 +3471,7 @@ fn findScalarInitializer(p: *Parser, il: **InitList, ty: *Type, actual_ty: Type, ty.* = elem_ty; il.* = try arr_il.find(p.gpa, index); if (il.*.node == .none and actual_ty.eql(elem_ty, p.comp, false)) return true; - if (try p.findScalarInitializer(il, ty, actual_ty, first_tok)) return true; + if (try p.findScalarInitializer(il, ty, res, first_tok)) return true; } return false; } else if (ty.get(.@"struct")) |struct_ty| { @@ -3490,7 +3491,8 @@ fn findScalarInitializer(p: *Parser, il: **InitList, ty: *Type, actual_ty: Type, ty.* = field.ty; il.* = try struct_il.find(p.gpa, index); if (il.*.node == .none and actual_ty.eql(field.ty, p.comp, false)) return true; - if (try p.findScalarInitializer(il, ty, actual_ty, first_tok)) return true; + if (il.*.node == .none and try p.coerceArrayInit(res, first_tok, ty.*)) return true; + if (try p.findScalarInitializer(il, ty, res, first_tok)) return true; } return false; } else if (ty.get(.@"union")) |union_ty| { @@ -3503,7 +3505,8 @@ fn findScalarInitializer(p: *Parser, il: **InitList, ty: *Type, actual_ty: Type, ty.* = union_ty.data.record.fields[0].ty; il.* = try il.*.find(p.gpa, 0); // if (il.*.node == .none and actual_ty.eql(ty, p.comp, false)) return true; - if (try p.findScalarInitializer(il, ty, actual_ty, first_tok)) return true; + if (try p.coerceArrayInit(res, first_tok, ty.*)) return true; + if (try p.findScalarInitializer(il, ty, res, first_tok)) return true; return false; } return il.*.node == .none; diff --git a/test/cases/initializers.c b/test/cases/initializers.c index 9eb7132b..62379d2e 100644 --- a/test/cases/initializers.c +++ b/test/cases/initializers.c @@ -131,6 +131,23 @@ void quux(void) { long *y = &x; unsigned int *z = &x; } +struct S2 { + char bytes[32]; +}; +union U { + char bytes[32]; +}; +union U2 { + int a; + char bytes[32]; +}; + +void array_members(void) { + struct S2 s = (struct S2){"ABC"}; + union U u = (union U){"ABC"}; + union U2 u2 = (union U2){"ABC"}; + char b[32] = (char[32]){"ABC"}; +} #define TESTS_SKIPPED 3 #define EXPECTED_ERRORS "initializers.c:2:17: error: variable-sized object may not be initialized" \ @@ -184,4 +201,5 @@ void quux(void) { "initializers.c:129:17: error: initializing 'void *' from incompatible type 'struct Foo'" \ "initializers.c:131:15: warning: incompatible pointer types initializing 'long *' from incompatible type 'int *' [-Wincompatible-pointer-types]" \ "initializers.c:132:23: warning: incompatible pointer types initializing 'unsigned int *' from incompatible type 'int *' converts between pointers to integer types with different sign [-Wpointer-sign]" \ + "initializers.c:148:30: warning: implicit pointer to integer conversion from 'char *' to 'int' [-Wint-conversion]" \