diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5963361f8..a1a26c35e 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -1158,6 +1158,7 @@ const expr_t *gather_factors (const type_t *type, int op, const expr_t **factors, int count); typedef struct rua_ctx_s rua_ctx_t; +void decl_process (const expr_t *expr, rua_ctx_t *ctx); const expr_t *expr_process (const expr_t *expr, rua_ctx_t *ctx); specifier_t spec_process (specifier_t spec, rua_ctx_t *ctx); bool can_inline (const expr_t *expr, symbol_t *fsym); diff --git a/tools/qfcc/include/rua-lang.h b/tools/qfcc/include/rua-lang.h index 630c43eb1..2de820bb9 100644 --- a/tools/qfcc/include/rua-lang.h +++ b/tools/qfcc/include/rua-lang.h @@ -217,6 +217,7 @@ typedef struct rua_ctx_s { struct rua_extra_s *extra; void *scanner; language_t *language; + bool extdecl; } rua_ctx_t; extern language_t lang_ruamoko; diff --git a/tools/qfcc/source/expr_process.c b/tools/qfcc/source/expr_process.c index 8be6dfcb0..b7a6250fa 100644 --- a/tools/qfcc/source/expr_process.c +++ b/tools/qfcc/source/expr_process.c @@ -758,7 +758,7 @@ proc_decl (const expr_t *expr, rua_ctx_t *ctx) } auto spec = decl_spec; spec.sym = sym; - if (spec.type_list) { + if (!ctx->extdecl && spec.type_list) { // to get here, a concrete declaration is being made spec.is_generic = false; spec = spec_process (spec, ctx); @@ -911,3 +911,11 @@ expr_process (const expr_t *expr, rua_ctx_t *ctx) } return proc; } + +void +decl_process (const expr_t *expr, rua_ctx_t *ctx) +{ + ctx->extdecl = true; + expr_process (expr, ctx); + ctx->extdecl = false; +} diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index cff82f1ba..612fa9e88 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -290,7 +290,7 @@ parse_generic_function (const char *name, specifier_t spec, rua_ctx_t *ctx) } // fake parameter for the return type param_t ret_param = { - .next = spec.sym->params, + .next = spec.params, .type = spec.type, .type_expr = spec.type_expr, }; @@ -352,6 +352,10 @@ parse_generic_function (const char *name, specifier_t spec, rua_ctx_t *ctx) } } + auto type = new_type (); + *type = type_func; + spec.sym->type = type; + num_params = 0; // skip return type so it can be done last to support complex expressions for (auto p = ret_param.next; p; p = p->next) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index dc8541836..d75c566cc 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -760,9 +760,9 @@ fndef ; datadef - : defspecs notype_initdecls ';' { expr_process ($2, ctx); } - | declspecs_nots notype_initdecls ';' { expr_process ($2, ctx); } - | declspecs_ts initdecls ';' { expr_process ($2, ctx); } + : defspecs notype_initdecls ';' { decl_process ($2, ctx); } + | declspecs_nots notype_initdecls ';' { decl_process ($2, ctx); } + | declspecs_ts initdecls ';' { decl_process ($2, ctx); } | declspecs_ts qc_func_params { $$ = qc_function_spec ($1, $2); @@ -1204,7 +1204,7 @@ save_storage function_body : method_optional_state_expr[state] { - specifier_t spec = spec_process ($0, ctx); + specifier_t spec = $0; spec.is_overload |= ctx->language->always_overload; spec.sym = function_symbol (spec, ctx); $$ = spec; @@ -1230,7 +1230,7 @@ function_body } | '=' '#' expr ';' { - specifier_t spec = spec_process ($0, ctx); + specifier_t spec = $0; const expr_t *bi_val = expr_process ($3, ctx); spec.is_overload |= ctx->language->always_overload; @@ -1239,7 +1239,7 @@ function_body } | '=' intrinsic { - specifier_t spec = spec_process ($0, ctx); + specifier_t spec = $0; build_intrinsic_function (spec, $2, ctx); } ;