diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 83b455555..15f32ddc3 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -41,7 +41,8 @@ #include "def.h" -#define MAX_DEF_SIZE ((int)PR_SIZEOF(lvec4)) +// The maximum size of a temp def, return value, or parameter value +#define MAX_DEF_SIZE 32 /** Represent an overloading of a function. @@ -152,6 +153,7 @@ param_t *check_params (param_t *params); enum storage_class_e; struct defspace_s; +int value_too_large (struct type_s *val_type) __attribute__((const)); void make_function (struct symbol_s *sym, const char *nice_name, struct defspace_s *space, enum storage_class_e storage); struct symbol_s *function_symbol (struct symbol_s *sym, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 65eeb2468..746a94f03 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2197,12 +2197,14 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) return e; } - if (!type_size (t)) + if (!type_size (t)) { err = error (e, "type of formal parameter %d is incomplete", i + 1); - if (type_size (t) > type_size (&type_param)) + } + if (value_too_large (t)) { err = error (e, "formal parameter %d is too large to be passed by" " value", i + 1); + } if (i < param_count) { if (e->type == ex_nil) convert_nil (e, t = ftype->t.func.param_types[i]); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index e9371ea81..d8642d588 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -459,6 +459,18 @@ find_function (expr_t *fexpr, expr_t *params) return fexpr; } +int +value_too_large (type_t *val_type) +{ + if ((options.code.progsversion < PROG_VERSION + && type_size (val_type) > type_size (&type_param)) + || (options.code.progsversion == PROG_VERSION + && type_size (val_type) > MAX_DEF_SIZE)) { + return 1; + } + return 0; +} + static void check_function (symbol_t *fsym) { @@ -470,7 +482,7 @@ check_function (symbol_t *fsym) error (0, "return type is an incomplete type"); fsym->type->t.func.type = &type_void;//FIXME better type? } - if (type_size (fsym->type->t.func.type) > type_size (&type_param)) { + if (value_too_large (fsym->type->t.func.type)) { error (0, "return value too large to be passed by value (%d)", type_size (&type_param)); fsym->type->t.func.type = &type_void;//FIXME better type? @@ -480,12 +492,14 @@ check_function (symbol_t *fsym) continue; // ellipsis marker if (!p->type) continue; // non-param selector - if (!type_size (p->type)) + if (!type_size (p->type)) { error (0, "parameter %d (ā€˜%sā€™) has incomplete type", i + 1, p->name); - if (type_size (p->type) > type_size (&type_param)) + } + if (value_too_large (p->type)) { error (0, "param %d (ā€˜%sā€™) is too large to be passed by value", i + 1, p->name); + } } }