diff --git a/tools/qfcc/source/expr_process.c b/tools/qfcc/source/expr_process.c index cfa319a55..c2246cf03 100644 --- a/tools/qfcc/source/expr_process.c +++ b/tools/qfcc/source/expr_process.c @@ -312,6 +312,16 @@ ps_file (const expr_t *e) return new_string_expr (GETSTR (e->loc.file)); } +static const expr_t * +ps_super (const expr_t *e) +{ + if (current_class && strcmp (e->symbol->name, "super") == 0) { + // FIXME check for in message receiver expr? + return e; + } + return nullptr; +} + static struct { const char *name; const expr_t *(*expr) (const expr_t *e); @@ -321,6 +331,7 @@ static struct { { .name = "__LINE__", .expr = ps_line }, { .name = "__INFINITY__", .expr = ps_infinity }, { .name = "__FILE__", .expr = ps_file }, + { .name = "super", .expr = ps_super }, {} }; @@ -332,7 +343,11 @@ proc_symbol (const expr_t *expr, rua_ctx_t *ctx) for (auto bi = builtin_names; bi->name; bi++) { if (strcmp (bi->name, sym->name) == 0) { scoped_src_loc (expr); - return bi->expr (expr); + auto e = bi->expr (expr); + if (e) { + return bi->expr (expr); + } + break; } } sym = symtab_lookup (current_symtab, sym->name); @@ -344,9 +359,9 @@ proc_symbol (const expr_t *expr, rua_ctx_t *ctx) return sym->convert.conv (sym, sym->convert.data); } scoped_src_loc (expr); - expr = new_symbol_expr (sym); + return new_symbol_expr (sym); } - return expr; + return error (expr, "undefined symbol `%s`", expr->symbol->name); } static bool diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 5fd9c641f..b1a6391b6 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -852,6 +852,17 @@ function_symbol (specifier_t spec) const char *name = sym->name; metafunc_t *func = Hash_Find (function_map, name); + auto check = symtab_lookup (current_symtab, name); + if ((sym->table == current_symtab && sym->sy_type != sy_func) + || (check && check->table == current_symtab + && check->sy_type != sy_func)) { + auto err = new_symbol (nullptr); + err->sy_type = sy_expr; + err->expr = error (0, "`%s` redeclared as different kind of symbol", + name); + return err; + } + auto genfunc = parse_generic_function (name, spec); if (genfunc) { add_generic_function (genfunc); @@ -879,6 +890,17 @@ function_symbol (specifier_t spec) s->type = unalias_type (sym->type); symtab_addsymbol (current_symtab, s); } + if (!sym->table && strcmp (s->name, sym->name) != 0) { + // record unmangled function symbol to avoid false undefined symbol + // errors + sym->sy_type = sy_func; + sym->metafunc = new_metafunc (); + *sym->metafunc = (metafunc_t) { + .name = save_string (name), + .meta_type = mf_overload, + }; + symtab_addsymbol (current_symtab, sym); + } //if it existed, override the declaration's parameters and metafunc s->params = sym->params; s->metafunc = func;