From c236129bbee4557a3fcc62bcde0cd86f79c21fd1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Aug 2024 14:37:18 +0900 Subject: [PATCH] [qfcc] Parse generic functions early Detecting generic functions needs to be done before finalizing the function type for non-generic functions, otherwise the resulting function type winds up being incorrect due to bogus resolution of the return type (and probably a few other factors). This takes care of handling the return type in function definitions as well as declarations as --- tools/qfcc/source/function.c | 85 +++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index ab17ae36c..89e7a70f0 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -305,6 +305,12 @@ parse_generic_function (const char *name, specifier_t spec) warning (0, "generic parameter %s not used", s->name); } } + if (!num_gentype) { + if (!spec.is_generic_block) { + warning (0, "no generic parameters for %s", name); + } + return nullptr; + } genfunc_t *genfunc; ALLOC (4096, genfunc_t, genfuncs, genfunc); @@ -508,28 +514,6 @@ static metafunc_t * get_function (const char *name, const type_t *type, specifier_t spec) { metafunc_t *func = Hash_Find (function_map, name); - - auto genfunc = parse_generic_function (name, spec); - //FIXME want to be able to provide specific overloads for generic functions - //but need to figure out details, so disallow for now. - if (genfunc) { - if (func && func->meta_type != mf_generic) { - error (0, "can't mix generic and simple or overload"); - return nullptr; - } - add_generic_function (genfunc); - - ALLOC (1024, metafunc_t, metafuncs, func); - *func = (metafunc_t) { - .name = save_string (name), - .full_name = name, - .loc = pr.loc, - .meta_type = mf_generic, - }; - Hash_Add (metafuncs, func); - Hash_Add (function_map, func); - return func; - } if (func && func->meta_type == mf_generic) { error (0, "can't mix generic and simple or overload"); return nullptr; @@ -579,23 +563,42 @@ get_function (const char *name, const type_t *type, specifier_t spec) symbol_t * function_symbol (specifier_t spec) { - if (!spec.is_generic && (!spec.sym->type || !spec.sym->type->encoding)) { - spec = default_type (spec, spec.sym); - spec.sym->type = append_type (spec.sym->type, spec.type); - set_func_type_attrs (spec.sym->type, spec); - spec.sym->type = find_type (spec.sym->type); - } - symbol_t *sym = spec.sym; const char *name = sym->name; - metafunc_t *func; - symbol_t *s; + metafunc_t *func = Hash_Find (function_map, name); - func = get_function (name, unalias_type (sym->type), spec); + auto genfunc = parse_generic_function (name, spec); + //FIXME want to be able to provide specific overloads for generic functions + //but need to figure out details, so disallow for now. + if (genfunc) { + if (func && func->meta_type != mf_generic) { + error (0, "can't mix generic and simple or overload"); + return nullptr; + } + add_generic_function (genfunc); + + ALLOC (1024, metafunc_t, metafuncs, func); + *func = (metafunc_t) { + .name = save_string (name), + .full_name = name, + .loc = pr.loc, + .meta_type = mf_generic, + }; + Hash_Add (metafuncs, func); + Hash_Add (function_map, func); + } else { + if (!spec.sym->type || !spec.sym->type->encoding) { + spec = default_type (spec, spec.sym); + spec.sym->type = append_type (spec.sym->type, spec.type); + set_func_type_attrs (spec.sym->type, spec); + spec.sym->type = find_type (spec.sym->type); + } + func = get_function (name, unalias_type (sym->type), spec); + } if (func && func->meta_type == mf_overload) name = func->full_name; - s = symtab_lookup (current_symtab, name); + symbol_t *s = symtab_lookup (current_symtab, name); if (!s || s->table != current_symtab) { s = new_symbol (name); s->sy_type = sy_func; @@ -777,7 +780,7 @@ find_generic_function (const expr_t *fexpr, genfunc_t **genfuncs, sym->sy_type = sy_func; sym->type = type; sym->params = params; - sym->metafunc = nullptr; + sym->metafunc = fsym->metafunc; symtab_addsymbol (fsym->table, sym); } return new_symbol_expr (sym); @@ -1299,16 +1302,20 @@ build_builtin_function (symbol_t *sym, const expr_t *bi_val, int far, error (bi_val, "%s is not a function", sym->name); return 0; } - function_t *func = sym->metafunc->func; - if (func && func->def && func->def->initialized) { - error (bi_val, "%s redefined", sym->name); - return 0; - } if (!is_int_val (bi_val) && !(type_default != &type_int && is_float_val (bi_val))) { error (bi_val, "invalid constant for = #"); return 0; } + if (sym->metafunc->meta_type == mf_generic) { + return 0; + } + + function_t *func = sym->metafunc->func; + if (func && func->def && func->def->initialized) { + error (bi_val, "%s redefined", sym->name); + return 0; + } defspace_t *space = far ? pr.far_data : sym->table->space; func = make_function (sym, 0, space, storage);