diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index ba3c4d292..3e36208dc 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -197,7 +197,7 @@ struct defspace_s; int value_too_large (const type_t *val_type) __attribute__((pure)); void make_function (symbol_t *sym, const char *nice_name, struct defspace_s *space, enum storage_class_e storage); -symbol_t *function_symbol (symbol_t *sym, specifier_t spec); +symbol_t *function_symbol (specifier_t spec); const expr_t *find_function (const expr_t *fexpr, const expr_t *params); function_t *begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, int far, diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 4c30e6b86..550da62f9 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1634,18 +1634,15 @@ class_finish_module (void) if (!exec_class_sym) { exec_class_sym = new_symbol_type ("__obj_exec_class", &type_exec_class); - exec_class_sym = function_symbol (exec_class_sym, - (specifier_t) { - .is_overload = false + exec_class_sym = function_symbol ((specifier_t) { + .sym = exec_class_sym }); make_function (exec_class_sym, 0, exec_class_sym->table->space, sc_extern); } init_sym = new_symbol_type (".ctor", &type_func); - init_sym = function_symbol (init_sym, (specifier_t) { - .is_overload = false - }); + init_sym = function_symbol ((specifier_t) { .sym = init_sym }); const expr_t *module_expr; module_expr = address_expr (new_symbol_expr (module_sym), 0); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 57ec506a9..bd4291dc2 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -3077,9 +3077,7 @@ think_expr (symbol_t *think_sym) } else { think_sym->type = &type_func; } - think_sym = function_symbol (think_sym, (specifier_t) { - .is_overload = false - }); + think_sym = function_symbol ((specifier_t) { .sym = think_sym }); make_function (think_sym, 0, current_symtab->space, current_storage); return new_symbol_expr (think_sym); } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 203a753bb..8abe15d9b 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -577,8 +577,16 @@ get_function (const char *name, const type_t *type, specifier_t spec) } symbol_t * -function_symbol (symbol_t *sym, specifier_t spec) +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; @@ -1104,12 +1112,18 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, if (sym->sy_type != sy_func) { error (0, "%s is not a function", sym->name); sym = new_symbol_type (sym->name, &type_func); - sym = function_symbol (sym, (specifier_t) { .is_overload = true }); + sym = function_symbol ((specifier_t) { + .sym = sym, + .is_overload = true + }); } if (sym->func && sym->func->def && sym->func->def->initialized) { error (0, "%s redefined", sym->name); sym = new_symbol_type (sym->name, sym->type); - sym = function_symbol (sym, (specifier_t) { .is_overload = true }); + sym = function_symbol ((specifier_t) { + .sym = sym, + .is_overload = true + }); } defspace_t *space = far ? pr.far_data : sym->table->space; diff --git a/tools/qfcc/source/glsl-parse.y b/tools/qfcc/source/glsl-parse.y index 5a9027d6f..53bb430e7 100644 --- a/tools/qfcc/source/glsl-parse.y +++ b/tools/qfcc/source/glsl-parse.y @@ -241,7 +241,10 @@ function_definition spec.sym->type = parse_params (spec.sym->type, spec.params); auto sym = function_sym_type (spec, spec.sym); sym->params = spec.params; - sym = function_symbol (sym, (specifier_t) { .is_overload = true }); + sym = function_symbol ((specifier_t) { + .sym = sym, + .is_overload = true + }); current_func = begin_function (sym, nullptr, current_symtab, false, spec.storage); current_symtab = current_func->locals; diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 0854fa719..b858e0968 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -183,7 +183,7 @@ method_symbol (class_type_t *class_type, method_t *method) //printf ("%s %s %s %ld\n", method->name, method->types, str->str, // str->size); sym = new_symbol_type (str->str, method->type); - sym = function_symbol (sym, (specifier_t) { .is_overload = false }); + sym = function_symbol ((specifier_t) { .sym = sym }); sym->params = method->params; dstring_delete (str); return sym; @@ -369,7 +369,7 @@ send_message (int super) symtab_t *save = current_symtab; current_symtab = pr.symtab; sym = new_symbol_type (sm_name, sm_type); - sym = function_symbol (sym, (specifier_t) { .is_overload = false }); + sym = function_symbol ((specifier_t) { .sym = sym }); make_function (sym, 0, sym->table->space, sc_extern); current_symtab = save; } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index f010c158f..055b20fce 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -432,8 +432,8 @@ function_spec (specifier_t spec, param_t *params) internal_error (0, "unexpected type"); } } + spec.is_function = !spec.sym->type; //FIXME do proper void(*)() -> ev_func spec.sym->type = append_type (spec.sym->type, parse_params (0, params)); - spec.is_function = true; //FIXME do proper void(*)() -> ev_func spec.is_generic = generic_scope; spec.is_generic_block = generic_block; spec.symtab = generic_symtab; @@ -498,13 +498,16 @@ qc_function_spec (specifier_t spec, param_t *params) return spec; } -static symbol_t * -function_sym_type (specifier_t spec, symbol_t *sym) +static specifier_t +qc_set_symbol (specifier_t spec, symbol_t *sym) { - sym->type = append_type (spec.sym->type, spec.type); - set_func_type_attrs (sym->type, spec); - sym->type = find_type (sym->type); - return sym; + // qc-style function declarations don't know the symbol name until the + // declaration is fully parsed, so spec.sym's name is null but its type + // carries any extra type information (field, pointer, array) + sym->params = spec.sym->params; + sym->type = spec.sym->type; + spec.sym = sym; + return spec; } static param_t * @@ -774,50 +777,23 @@ qc_func_decl qc_nocode_func : identifier '=' '#' expr { - specifier_t spec = $0; - symbol_t *sym = $1; + specifier_t spec = qc_set_symbol ($0, $1); const expr_t *bi_val = $4; - sym->params = spec.sym->params; - if (!spec.is_generic) { - sym = function_sym_type (spec, sym); - } - sym = function_symbol (sym, spec); + symbol_t *sym = function_symbol (spec); build_builtin_function (sym, bi_val, 0, spec.storage); } | identifier '=' expr { - specifier_t spec = $0; - symbol_t *sym = $1; + specifier_t spec = qc_set_symbol ($0, $1); const expr_t *expr = $3; - sym->params = spec.sym->params; - sym = function_sym_type (spec, sym); - sym = function_symbol (sym, spec); - spec.sym = sym; - spec.type = sym->type; - spec.is_function = false; - sym->type = nullptr; + declare_symbol (spec, expr, current_symtab); } | identifier { - specifier_t spec = $0; - symbol_t *sym = $1; - sym->params = spec.sym->params; - sym = function_sym_type (spec, sym); - if (!local_expr && !is_field (spec.sym->type)) { - sym = function_symbol (sym, spec); - } - if (!local_expr && !is_field (sym->type)) { - // things might be a confused mess from earlier errors - if (sym->sy_type == sy_func) - make_function (sym, 0, sym->table->space, spec.storage); - } else { - initialize_def (sym, 0, current_symtab->space, spec.storage, - current_symtab); - if (sym->def) - sym->def->nosave |= spec.nosave; - } + specifier_t spec = qc_set_symbol ($0, $1); + declare_symbol (spec, nullptr, current_symtab); } ; @@ -829,11 +805,8 @@ qc_code_func .symtab = current_symtab, .function = current_func, }; - specifier_t spec = $0; - symbol_t *sym = $1; - sym->params = spec.sym->params; - sym = function_sym_type (spec, sym); - sym = function_symbol (sym, spec); + specifier_t spec = qc_set_symbol ($0, $1); + symbol_t *sym = function_symbol (spec); current_func = begin_function (sym, 0, current_symtab, 0, spec.storage); current_symtab = current_func->locals; @@ -1134,8 +1107,7 @@ function_body : method_optional_state_expr { specifier_t spec = default_type ($0, $0.sym); - symbol_t *sym = function_sym_type (spec, spec.sym); - $$ = function_symbol (sym, spec); + $$ = function_symbol (spec); } save_storage { @@ -1158,14 +1130,9 @@ function_body | '=' '#' expr ';' { specifier_t spec = $0; - symbol_t *sym = spec.sym; const expr_t *bi_val = $3; - if (!spec.is_generic) { - spec = default_type (spec, spec.sym); - sym = function_sym_type (spec, sym); - } - sym = function_symbol (sym, spec); + symbol_t *sym = function_symbol (spec); build_builtin_function (sym, bi_val, 0, spec.storage); } ; @@ -2914,7 +2881,7 @@ qc_process_keyword (QC_YYSTYPE *lval, keyword_t *keyword, const char *token) }; return QC_TYPE_NAME; } - // id has been redelcared as a variable (hopefully) + // id has been redeclared as a variable (hopefully) return QC_NAME; } else { lval->spec = keyword->spec; diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 54734efa2..0fd934a2e 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -169,7 +169,7 @@ build_dotmain (symbol_t *program) dotmain->params = 0; dotmain->type = parse_params (&type_int, 0); dotmain->type = find_type (dotmain->type); - dotmain = function_symbol (dotmain, (specifier_t) { .is_overload = false }); + dotmain = function_symbol ((specifier_t) { .sym = dotmain }); exitcode = new_symbol_expr (symtab_lookup (current_symtab, "ExitCode")); @@ -252,7 +252,7 @@ program_head } $$->type = parse_params (&type_void, 0); $$->type = find_type ($$->type); - $$ = function_symbol ($$, (specifier_t) { .is_overload = false }); + $$ = function_symbol ((specifier_t) { .sym = $$ }); } ; @@ -339,9 +339,7 @@ subprogram_head $$->params = $3; $$->type = parse_params ($5, $3); $$->type = find_type ($$->type); - $$ = function_symbol ($$, (specifier_t) { - .is_overload = false - }); + $$ = function_symbol ((specifier_t) { .sym = $$ }); } } | PROCEDURE ID arguments @@ -353,9 +351,7 @@ subprogram_head $$->params = $3; $$->type = parse_params (&type_void, $3); $$->type = find_type ($$->type); - $$ = function_symbol ($$, (specifier_t) { - .is_overload = false - }); + $$ = function_symbol ((specifier_t) { .sym = $$ }); } } ; diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index b39e53b44..d50d9696f 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -272,15 +272,9 @@ declare_symbol (specifier_t spec, const expr_t *init, symtab_t *symtab) space = pr.near_data; } - if (spec.type) { + if (spec.type && (spec.is_typedef || !s->type || !is_func (s->type))) { s->type = append_type (spec.sym->type, spec.type); } - //FIXME is_function is bad (this whole implementation of handling - //function prototypes is bad), and is actually broken for function - //pointers - if (spec.is_function && is_func (s->type)) { - set_func_type_attrs (s->type, spec); - } if (spec.is_typedef) { if (init) { @@ -295,10 +289,7 @@ declare_symbol (specifier_t spec, const expr_t *init, symtab_t *symtab) if (init) { error (0, "function %s is initialized", s->name); } - if (!spec.type_expr) { - s->type = find_type (s->type); - } - s = function_symbol (s, spec); + s = function_symbol (spec); } else { s->type = find_type (s->type); initialize_def (s, init, space, spec.storage, symtab);