mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Support compound literals for struct #raw_union types
This commit is contained in:
+48
-4
@@ -6557,10 +6557,54 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
|||||||
break; // NOTE(bill): No need to init
|
break; // NOTE(bill): No need to init
|
||||||
}
|
}
|
||||||
if (t->Struct.is_raw_union) {
|
if (t->Struct.is_raw_union) {
|
||||||
if (cl->elems.count != 0) {
|
if (cl->elems.count > 0) {
|
||||||
gbString type_str = type_to_string(type);
|
// NOTE: unions cannot be constant
|
||||||
error(node, "Illegal compound literal type '%s'", type_str);
|
is_constant = false;
|
||||||
gb_string_free(type_str);
|
|
||||||
|
if (cl->elems[0]->kind != Ast_FieldValue) {
|
||||||
|
gbString type_str = type_to_string(type);
|
||||||
|
error(node, "%s ('struct #raw_union') compound literals are only allowed to contain 'field = value' elements", type_str);
|
||||||
|
gb_string_free(type_str);
|
||||||
|
} else {
|
||||||
|
if (cl->elems.count != 1) {
|
||||||
|
gbString type_str = type_to_string(type);
|
||||||
|
error(node, "%s ('struct #raw_union') compound literals are only allowed to contain up to 1 'field = value' element, got %td", type_str, cl->elems.count);
|
||||||
|
gb_string_free(type_str);
|
||||||
|
} else {
|
||||||
|
Ast *elem = cl->elems[0];
|
||||||
|
ast_node(fv, FieldValue, elem);
|
||||||
|
if (fv->field->kind != Ast_Ident) {
|
||||||
|
gbString expr_str = expr_to_string(fv->field);
|
||||||
|
error(elem, "Invalid field name '%s' in structure literal", expr_str);
|
||||||
|
gb_string_free(expr_str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = fv->field->Ident.token.string;
|
||||||
|
|
||||||
|
Selection sel = lookup_field(type, name, o->mode == Addressing_Type);
|
||||||
|
bool is_unknown = sel.entity == nullptr;
|
||||||
|
if (is_unknown) {
|
||||||
|
error(elem, "Unknown field '%.*s' in structure literal", LIT(name));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sel.index.count > 1) {
|
||||||
|
error(elem, "Cannot assign to an anonymous field '%.*s' in a structure literal (at the moment)", LIT(name));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity *field = t->Struct.fields[sel.index[0]];
|
||||||
|
add_entity_use(c, fv->field, field);
|
||||||
|
|
||||||
|
Operand o = {};
|
||||||
|
check_expr_or_type(c, &o, fv->value, field->type);
|
||||||
|
|
||||||
|
|
||||||
|
check_assignment(c, &o, field->type, str_lit("structure literal"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-2
@@ -6839,6 +6839,10 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
|
|||||||
return lb_const_nil(m, original_type);
|
return lb_const_nil(m, original_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_type_raw_union(type)) {
|
||||||
|
return lb_const_nil(m, original_type);
|
||||||
|
}
|
||||||
|
|
||||||
isize offset = 0;
|
isize offset = 0;
|
||||||
if (type->Struct.custom_align > 0) {
|
if (type->Struct.custom_align > 0) {
|
||||||
offset = 1;
|
offset = 1;
|
||||||
@@ -13464,6 +13468,8 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
TypeStruct *st = &bt->Struct;
|
TypeStruct *st = &bt->Struct;
|
||||||
if (cl->elems.count > 0) {
|
if (cl->elems.count > 0) {
|
||||||
lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
|
lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
|
||||||
|
lbValue comp_lit_ptr = lb_addr_get_ptr(p, v);
|
||||||
|
|
||||||
for_array(field_index, cl->elems) {
|
for_array(field_index, cl->elems) {
|
||||||
Ast *elem = cl->elems[field_index];
|
Ast *elem = cl->elems[field_index];
|
||||||
|
|
||||||
@@ -13492,6 +13498,12 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
|
|
||||||
field_expr = lb_build_expr(p, elem);
|
field_expr = lb_build_expr(p, elem);
|
||||||
|
|
||||||
|
lbValue gep = {};
|
||||||
|
if (is_raw_union) {
|
||||||
|
gep = lb_emit_conv(p, comp_lit_ptr, alloc_type_pointer(ft));
|
||||||
|
} else {
|
||||||
|
gep = lb_emit_struct_ep(p, comp_lit_ptr, cast(i32)index);
|
||||||
|
}
|
||||||
|
|
||||||
Type *fet = field_expr.type;
|
Type *fet = field_expr.type;
|
||||||
GB_ASSERT(fet->kind != Type_Tuple);
|
GB_ASSERT(fet->kind != Type_Tuple);
|
||||||
@@ -13500,11 +13512,9 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
|||||||
if (is_type_union(ft) && !are_types_identical(fet, ft) && !is_type_untyped(fet)) {
|
if (is_type_union(ft) && !are_types_identical(fet, ft) && !is_type_untyped(fet)) {
|
||||||
GB_ASSERT_MSG(union_variant_index(ft, fet) > 0, "%s", type_to_string(fet));
|
GB_ASSERT_MSG(union_variant_index(ft, fet) > 0, "%s", type_to_string(fet));
|
||||||
|
|
||||||
lbValue gep = lb_emit_struct_ep(p, lb_addr_get_ptr(p, v), cast(i32)index);
|
|
||||||
lb_emit_store_union_variant(p, gep, field_expr, fet);
|
lb_emit_store_union_variant(p, gep, field_expr, fet);
|
||||||
} else {
|
} else {
|
||||||
lbValue fv = lb_emit_conv(p, field_expr, ft);
|
lbValue fv = lb_emit_conv(p, field_expr, ft);
|
||||||
lbValue gep = lb_emit_struct_ep(p, lb_addr_get_ptr(p, v), cast(i32)index);
|
|
||||||
lb_emit_store(p, gep, fv);
|
lb_emit_store(p, gep, fv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user