Extra check for type_info cycle checking

This commit is contained in:
gingerBill
2018-01-28 09:51:52 +00:00
parent f661ae9d09
commit 83d90f1463
3 changed files with 31 additions and 9 deletions
+26 -9
View File
@@ -3242,23 +3242,40 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
} }
case BuiltinProc_type_of: case BuiltinProc_type_of: {
// proc type_of(val: Type) -> type(Type) // proc type_of(val: Type) -> type(Type)
check_assignment(c, operand, nullptr, str_lit("argument of 'type_of'")); AstNode *expr = ce->args[0];
if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin) { Operand o = {};
check_expr_or_type(c, &o, expr);
// check_assignment(c, operand, nullptr, str_lit("argument of 'type_of'"));
if (o.mode == Addressing_Invalid || o.mode == Addressing_Builtin) {
return false; return false;
} }
if (operand->type == nullptr || operand->type == t_invalid) { if (o.type == nullptr || o.type == t_invalid) {
error(operand->expr, "Invalid argument to 'type_of'"); error(o.expr, "Invalid argument to 'type_of'");
return false; return false;
} }
if (is_type_polymorphic(operand->type)) { if (o.type == nullptr || o.type == t_invalid) {
error(operand->expr, "'type_of' of polymorphic type cannot be determined"); error(o.expr, "Invalid argument to 'type_of'");
return false;
}
// NOTE(bill): Prevent type cycles for procedure declarations
if (c->context.curr_proc_sig == o.type) {
gbString s = expr_to_string(o.expr);
error(o.expr, "Invalid cyclic type usage from 'type_of', got '%s'", s);
gb_string_free(s);
return false;
}
if (is_type_polymorphic(o.type)) {
error(o.expr, "'type_of' of polymorphic type cannot be determined");
return false; return false;
} }
operand->mode = Addressing_Type; operand->mode = Addressing_Type;
operand->type = o.type;
break; break;
}
case BuiltinProc_type_info_of: { case BuiltinProc_type_info_of: {
// proc type_info_of(Type) -> ^Type_Info // proc type_info_of(Type) -> ^Type_Info
@@ -3270,7 +3287,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
init_preload(c); init_preload(c);
AstNode *expr = ce->args[0]; AstNode *expr = ce->args[0];
Operand o = {}; Operand o = {};
check_expr_or_type(c, &o, ce->args[0]); check_expr_or_type(c, &o, expr);
if (o.mode == Addressing_Invalid) { if (o.mode == Addressing_Invalid) {
return false; return false;
} }
+4
View File
@@ -1671,6 +1671,10 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
c->context.polymorphic_scope = c->context.scope; c->context.polymorphic_scope = c->context.scope;
} }
CheckerContext prev = c->context;
defer (c->context = prev);
c->context.curr_proc_sig = type;
bool variadic = false; bool variadic = false;
isize variadic_index = -1; isize variadic_index = -1;
bool success = true; bool success = true;
+1
View File
@@ -275,6 +275,7 @@ struct CheckerContext {
String proc_name; String proc_name;
Type * type_hint; Type * type_hint;
DeclInfo * curr_proc_decl; DeclInfo * curr_proc_decl;
Type * curr_proc_sig;
ForeignContext foreign_context; ForeignContext foreign_context;
bool collect_delayed_decls; bool collect_delayed_decls;