From e64eb74eef40c4c79b493006feadce4499a8a9dd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 27 Jan 2021 15:27:38 +0000 Subject: [PATCH] Fix #831 --- src/check_expr.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++ src/checker.cpp | 7 +++++-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 63b275c99..b001ed7a8 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1801,6 +1801,50 @@ void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *node) { o->mode = Addressing_Value; } +void add_comparison_procedures_for_fields(CheckerContext *c, Type *t) { + if (t == nullptr) { + return; + } + t = base_type(t); + if (!is_type_comparable(t)) { + return; + } + switch (t->kind) { + case Type_Basic: + switch (t->Basic.kind) { + case Basic_complex64: + add_package_dependency(c, "runtime", "complex64_eq"); + add_package_dependency(c, "runtime", "complex64_ne"); + break; + case Basic_complex128: + add_package_dependency(c, "runtime", "complex128_eq"); + add_package_dependency(c, "runtime", "complex128_ne"); + break; + case Basic_quaternion128: + add_package_dependency(c, "runtime", "quaternion128_eq"); + add_package_dependency(c, "runtime", "quaternion128_ne"); + break; + case Basic_quaternion256: + add_package_dependency(c, "runtime", "quaternion256_eq"); + add_package_dependency(c, "runtime", "quaternion256_ne"); + break; + case Basic_cstring: + add_package_dependency(c, "runtime", "cstring_to_string"); + /*fallthrough*/ + case Basic_string: + add_package_dependency(c, "runtime", "string_eq"); + add_package_dependency(c, "runtime", "string_ne"); + break; + } + break; + case Type_Struct: + for_array(i, t->Struct.fields) { + add_comparison_procedures_for_fields(c, t->Struct.fields[i]->type); + } + break; + } +} + void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) { if (x->mode == Addressing_Type && y->mode == Addressing_Type) { @@ -1867,6 +1911,13 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) { defer (gb_string_free(type_string)); err_str = gb_string_make(temporary_allocator(), gb_bprintf("operator '%.*s' not defined for type '%s'", LIT(token_strings[op]), type_string)); + } else { + Type *comparison_type = x->type; + if (x->type == err_type && is_operand_nil(*x)) { + comparison_type = y->type; + } + + add_comparison_procedures_for_fields(c, comparison_type); } } else { gbString xt, yt; diff --git a/src/checker.cpp b/src/checker.cpp index 1e1eac984..c7dbc7b2f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3,7 +3,7 @@ void check_expr(CheckerContext *c, Operand *operand, Ast *expression); void check_expr_or_type(CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint=nullptr); - +void add_comparison_procedures_for_fields(CheckerContext *c, Type *t); bool is_operand_value(Operand o) { switch (o.mode) { @@ -648,8 +648,8 @@ void add_package_dependency(CheckerContext *c, char const *package_name, char co AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name)); Entity *e = scope_lookup(p->scope, n); GB_ASSERT_MSG(e != nullptr, "%s", name); + GB_ASSERT(c->decl != nullptr); ptr_set_add(&c->decl->deps, e); - // add_type_info_type(c, e->type); } void add_declaration_dependency(CheckerContext *c, Entity *e) { @@ -1425,6 +1425,7 @@ void add_type_info_type(CheckerContext *c, Type *t) { Entity *f = bt->Struct.fields[i]; add_type_info_type(c, f->type); } + add_comparison_procedures_for_fields(c, bt); break; case Type_BitFieldValue: @@ -4453,6 +4454,7 @@ void check_parsed_files(Checker *c) { CheckerContext prev_context = c->init_ctx; defer (c->init_ctx = prev_context); + c->init_ctx.decl = make_decl_info(nullptr, nullptr); TIME_SECTION("check procedure bodies"); // NOTE(bill): Nested procedures bodies will be added to this "queue" @@ -4514,6 +4516,7 @@ void check_parsed_files(Checker *c) { if (align > 0 && ptr_set_exists(&c->info.minimum_dependency_set, e)) { add_type_info_type(&c->init_ctx, e->type); } + } else if (e->kind == Entity_Procedure) { DeclInfo *decl = e->decl_info; ast_node(pl, ProcLit, decl->proc_lit);