aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-10-01 21:22:39 +0100
committerGinger Bill <bill@gingerbill.org>2017-10-01 21:22:39 +0100
commitee904060c5e96073c775eaf1ebbe1d6b2d833928 (patch)
tree55083ff473d7d7a4a058944beb34eacf79f0b679 /src
parentafb5538e832d7772b5149c899e78ccb8edf2dde3 (diff)
Disallow anonymous structs with procedures as default values
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp5
-rw-r--r--src/ir.cpp80
2 files changed, 63 insertions, 22 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index ceac342b4..c21f56c22 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -3301,6 +3301,11 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
check_struct_type(c, *type, e, nullptr, named_type);
check_close_scope(c);
(*type)->Struct.node = e;
+
+ if (named_type == nullptr && (*type)->Struct.has_proc_default_values) {
+ error(e, "Anonymous structs cannot have procedures as default values");
+ }
+
return true;
case_end;
diff --git a/src/ir.cpp b/src/ir.cpp
index 2c874584f..d5109e074 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -3754,6 +3754,39 @@ irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, AstNode *exp
return value;
}
+void ir_check_type_and_gen_for_proc_lit(irProcedure *proc, Type *t) {
+ if (t == nullptr) return;
+ if (t->kind == Type_Struct && t->Struct.has_proc_default_values) {
+ for_array(i, t->Struct.fields) {
+ Entity *f = t->Struct.fields[i];
+ if (f->kind == Entity_Variable && f->Variable.default_value.kind == ExactValue_Procedure) {
+ AstNode *expr = f->Variable.default_value.value_procedure;
+ GB_ASSERT(expr != nullptr);
+ if (expr->kind == AstNode_ProcLit) {
+ ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc);
+ }
+ }
+ }
+ }
+}
+
+void ir_check_type_and_gen_for_proc_lit(irModule *m, String prefix_name, Type *t) {
+ if (t == nullptr) return;
+ if (t->kind == Type_Struct && t->Struct.has_proc_default_values) {
+ for_array(i, t->Struct.fields) {
+ Entity *f = t->Struct.fields[i];
+ if (f->kind == Entity_Variable && f->Variable.default_value.kind == ExactValue_Procedure) {
+ AstNode *expr = f->Variable.default_value.value_procedure;
+ GB_ASSERT(expr != nullptr);
+ if (expr->kind == AstNode_ProcLit) {
+ ir_gen_anonymous_proc_lit(m, prefix_name, expr);
+ }
+ }
+ }
+ }
+}
+
+
void ir_gen_global_type_name(irModule *m, Entity *e, String name) {
if (e->type == nullptr) return;
@@ -3805,22 +3838,7 @@ void ir_gen_global_type_name(irModule *m, Entity *e, String name) {
// }
// }
- if (bt->kind == Type_Struct) {
- if (bt->Struct.has_proc_default_values) {
- for_array(i, bt->Struct.fields) {
- Entity *f = bt->Struct.fields[i];
- if (f->kind == Entity_Variable) {
- if (f->Variable.default_value.kind == ExactValue_Procedure) {
- AstNode *expr = f->Variable.default_value.value_procedure;
- GB_ASSERT(expr != nullptr);
- if (expr->kind == AstNode_ProcLit) {
- ir_gen_anonymous_proc_lit(m, e->token.string, expr);
- }
- }
- }
- }
- }
- }
+ ir_check_type_and_gen_for_proc_lit(m, e->token.string, bt);
}
@@ -6389,8 +6407,9 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
ir_add_local_for_identifier(proc, name, false);
lval = ir_build_addr(proc, name);
}
-
array_add(&lvals, lval);
+
+ ir_check_type_and_gen_for_proc_lit(proc, ir_addr_type(lval));
}
for_array(i, vd->values) {
@@ -7428,11 +7447,15 @@ void ir_build_proc(irValue *value, irProcedure *parent) {
auto *p = &proc->type->Proc;
for_array(i, p->params->Tuple.variables) {
Entity *f = p->params->Tuple.variables[i];
- if (f->kind == Entity_Variable && f->Variable.default_value.kind == ExactValue_Procedure) {
- AstNode *expr = f->Variable.default_value.value_procedure;
- GB_ASSERT(expr != nullptr);
- if (expr->kind == AstNode_ProcLit) {
- ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc);
+ if (f->kind == Entity_Variable) {
+ if (f->Variable.default_value.kind == ExactValue_Procedure) {
+ AstNode *expr = f->Variable.default_value.value_procedure;
+ GB_ASSERT(expr != nullptr);
+ if (expr->kind == AstNode_ProcLit) {
+ ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc);
+ }
+ } else {
+ ir_check_type_and_gen_for_proc_lit(proc, f->type);
}
}
}
@@ -7781,6 +7804,19 @@ void ir_gen_tree(irGen *s) {
var.var = g;
var.decl = decl;
+ if (e->type->kind == Type_Struct && e->type->Struct.has_proc_default_values) {
+ for_array(i, e->type->Struct.fields) {
+ Entity *f = e->type->Struct.fields[i];
+ if (f->kind == Entity_Variable && f->Variable.default_value.kind == ExactValue_Procedure) {
+ AstNode *expr = f->Variable.default_value.value_procedure;
+ GB_ASSERT(expr != nullptr);
+ if (expr->kind == AstNode_ProcLit) {
+ ir_gen_anonymous_proc_lit(m, e->token.string, expr);
+ }
+ }
+ }
+ }
+
if (decl->init_expr != nullptr) {
if (is_type_any(e->type)) {
} else {