diff options
| author | gingerBill <bill@gingerbill.org> | 2018-01-28 09:51:52 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2018-01-28 09:51:52 +0000 |
| commit | 83d90f146398bf6cff751d239406328dbb95e724 (patch) | |
| tree | 98deb3f41f9282f4b725606d09d01e1d6bbacf4d | |
| parent | f661ae9d095b4b7d6e8a51f7b539612afe4162a0 (diff) | |
Extra check for `type_info` cycle checking
| -rw-r--r-- | src/check_expr.cpp | 35 | ||||
| -rw-r--r-- | src/check_type.cpp | 4 | ||||
| -rw-r--r-- | src/checker.hpp | 1 |
3 files changed, 31 insertions, 9 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 2725447c4..9b25f2655 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -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) - check_assignment(c, operand, nullptr, str_lit("argument of 'type_of'")); - if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin) { + AstNode *expr = ce->args[0]; + 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; + } + if (o.type == nullptr || o.type == t_invalid) { + error(o.expr, "Invalid argument to 'type_of'"); + return false; + } + if (o.type == nullptr || o.type == t_invalid) { + error(o.expr, "Invalid argument to 'type_of'"); return false; } - if (operand->type == nullptr || operand->type == t_invalid) { - error(operand->expr, "Invalid argument to 'type_of'"); + // 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(operand->type)) { - error(operand->expr, "'type_of' of polymorphic type cannot be determined"); + + if (is_type_polymorphic(o.type)) { + error(o.expr, "'type_of' of polymorphic type cannot be determined"); return false; } operand->mode = Addressing_Type; + operand->type = o.type; break; - + } case BuiltinProc_type_info_of: { // 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); AstNode *expr = ce->args[0]; Operand o = {}; - check_expr_or_type(c, &o, ce->args[0]); + check_expr_or_type(c, &o, expr); if (o.mode == Addressing_Invalid) { return false; } diff --git a/src/check_type.cpp b/src/check_type.cpp index 41c975185..4beb88bdb 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1671,6 +1671,10 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array c->context.polymorphic_scope = c->context.scope; } + CheckerContext prev = c->context; + defer (c->context = prev); + c->context.curr_proc_sig = type; + bool variadic = false; isize variadic_index = -1; bool success = true; diff --git a/src/checker.hpp b/src/checker.hpp index f3507d2d5..29b8eae1a 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -275,6 +275,7 @@ struct CheckerContext { String proc_name; Type * type_hint; DeclInfo * curr_proc_decl; + Type * curr_proc_sig; ForeignContext foreign_context; bool collect_delayed_decls; |