aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2025-09-28 21:47:56 +0100
committergingerBill <gingerBill@users.noreply.github.com>2025-09-28 21:47:56 +0100
commit8be18d9a401f898320b57379488bad1367632628 (patch)
treefef9a5b31bf48a673206e769778c96deffcd45b2 /src
parent35a32d41e03ad10134d7705e4e502c1a23f39d47 (diff)
Allow for constant `[]typeid`
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.cpp21
-rw-r--r--src/check_expr.cpp27
-rw-r--r--src/types.cpp30
3 files changed, 61 insertions, 17 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index bda1059fb..842f8653c 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -1686,7 +1686,28 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *e, Ast
check_expr_with_type_hint(ctx, &o, init_expr, e->type);
check_init_variable(ctx, e, &o, str_lit("variable declaration"));
if (e->Variable.is_rodata && o.mode != Addressing_Constant) {
+ ERROR_BLOCK();
error(o.expr, "Variables declared with @(rodata) must have constant initialization");
+ Ast *expr = unparen_expr(o.expr);
+ if (is_type_struct(e->type) && expr && expr->kind == Ast_CompoundLit) {
+ ast_node(cl, CompoundLit, expr);
+ for (Ast *elem_ : cl->elems) {
+ Ast *elem = elem_;
+ if (elem->kind == Ast_FieldValue) {
+ elem = elem->FieldValue.value;
+ }
+ elem = unparen_expr(elem);
+
+ Entity *e = entity_of_node(elem);
+ if (elem->tav.mode != Addressing_Constant && e == nullptr && elem->kind != Ast_ProcLit) {
+ Token tok = ast_token(elem);
+ TokenPos pos = tok.pos;
+ gbString s = type_to_string(type_of_expr(elem));
+ error_line("%s Element is not constant, which is required for @(rodata), of type %s\n", token_pos_to_string(pos), s);
+ gb_string_free(s);
+ }
+ }
+ }
}
check_rtti_type_disallowed(e->token, e->type, "A variable declaration is using a type, %s, which has been disallowed");
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index ebf61ab0c..3c37284eb 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -8655,7 +8655,7 @@ gb_internal bool check_range(CheckerContext *c, Ast *node, bool is_for_loop, Ope
return true;
}
-gb_internal bool check_is_operand_compound_lit_constant(CheckerContext *c, Operand *o) {
+gb_internal bool check_is_operand_compound_lit_constant(CheckerContext *c, Operand *o, Type *field_type) {
if (is_operand_nil(*o)) {
return true;
}
@@ -8670,6 +8670,9 @@ gb_internal bool check_is_operand_compound_lit_constant(CheckerContext *c, Opera
return true;
}
}
+ if (field_type != nullptr && is_type_typeid(field_type) && o->mode == Addressing_Type) {
+ return true;
+ }
return o->mode == Addressing_Constant;
}
@@ -9620,8 +9623,7 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slice<As
break;
}
}
- if (is_constant &&
- (is_type_any(ft) || is_type_union(ft) || is_type_raw_union(ft) || is_type_typeid(ft))) {
+ if (is_constant && elem_cannot_be_constant(ft)) {
is_constant = false;
}
}
@@ -9656,11 +9658,11 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slice<As
Operand o = {};
check_expr_or_type(c, &o, fv->value, field->type);
- if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) {
+ if (elem_cannot_be_constant(field->type)) {
is_constant = false;
}
if (is_constant) {
- is_constant = check_is_operand_compound_lit_constant(c, &o);
+ is_constant = check_is_operand_compound_lit_constant(c, &o, field->type);
}
u8 prev_bit_field_bit_size = c->bit_field_bit_size;
@@ -9886,14 +9888,11 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
Operand o = {};
check_expr_or_type(c, &o, elem, field->type);
- if (is_type_any(field->type) ||
- is_type_raw_union(field->type) ||
- (is_type_union(field->type) && !is_type_union_constantable(field->type)) ||
- is_type_typeid(field->type)) {
+ if (elem_cannot_be_constant(field->type)) {
is_constant = false;
}
if (is_constant) {
- is_constant = check_is_operand_compound_lit_constant(c, &o);
+ is_constant = check_is_operand_compound_lit_constant(c, &o, field->type);
}
check_assignment(c, &o, field->type, str_lit("structure literal"));
@@ -10070,7 +10069,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
check_expr_with_type_hint(c, &operand, fv->value, elem_type);
check_assignment(c, &operand, elem_type, context_name);
- is_constant = is_constant && operand.mode == Addressing_Constant;
+ if (is_constant) {
+ is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type);
+ }
}
}
@@ -10097,7 +10098,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
check_expr_with_type_hint(c, &operand, e, elem_type);
check_assignment(c, &operand, elem_type, context_name);
- is_constant = is_constant && operand.mode == Addressing_Constant;
+ if (is_constant) {
+ is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type);
+ }
}
if (max < index) {
diff --git a/src/types.cpp b/src/types.cpp
index 46e41bb4b..814f99eff 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -1377,14 +1377,20 @@ gb_internal bool is_type_ordered_numeric(Type *t) {
gb_internal bool is_type_constant_type(Type *t) {
t = core_type(t);
if (t == nullptr) { return false; }
- if (t->kind == Type_Basic) {
+ switch (t->kind) {
+ case Type_Basic:
+ if (t->Basic.kind == Basic_typeid) {
+ return true;
+ }
return (t->Basic.flags & BasicFlag_ConstantType) != 0;
- }
- if (t->kind == Type_BitSet) {
+ case Type_BitSet:
return true;
- }
- if (t->kind == Type_Proc) {
+ case Type_Proc:
return true;
+ case Type_Array:
+ return is_type_constant_type(t->Array.elem);
+ case Type_EnumeratedArray:
+ return is_type_constant_type(t->EnumeratedArray.elem);
}
return false;
}
@@ -2539,6 +2545,20 @@ gb_internal bool elem_type_can_be_constant(Type *t) {
return true;
}
+gb_internal bool elem_cannot_be_constant(Type *t) {
+ if (is_type_any(t)) {
+ return true;
+ }
+ if (is_type_union(t)) {
+ return !is_type_union_constantable(t);
+ }
+ if (is_type_raw_union(t)) {
+ return true;
+ }
+ return false;
+}
+
+
gb_internal bool is_type_lock_free(Type *t) {
t = core_type(t);
if (t == t_invalid) {