diff --git a/tools/qfcc/include/specifier.h b/tools/qfcc/include/specifier.h index 46534b06c..bcc0ce8a9 100644 --- a/tools/qfcc/include/specifier.h +++ b/tools/qfcc/include/specifier.h @@ -81,9 +81,6 @@ typedef struct specifier_s { bool is_generic:1; bool is_generic_block:1; bool is_function:1;//FIXME do proper void(*)() -> ev_func - bool nosave:1; - bool no_va_list:1; - bool void_return:1; }; unsigned spec_bits; }; diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 54aac865e..860e16d21 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -161,7 +161,6 @@ void chain_type (type_t *type); level. */ const type_t *append_type (const type_t *type, const type_t *new); -void set_func_type_attrs (const type_t *func, specifier_t spec); specifier_t default_type (specifier_t spec, const struct symbol_s *sym); const type_t *find_type (const type_t *new); void new_typedef (const char *name, type_t *type); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index a3814e3d8..389479f56 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -46,6 +46,7 @@ #include "QF/va.h" #include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/attribute.h" #include "tools/qfcc/include/class.h" #include "tools/qfcc/include/def.h" #include "tools/qfcc/include/defspace.h" @@ -681,6 +682,18 @@ initialize_def (symbol_t *sym, const expr_t *init, defspace_t *space, sym->def->initializer = init; } +static void +set_def_attributes (def_t *def, attribute_t *attr_list) +{ + for (attribute_t *attr = attr_list; attr; attr = attr->next) { + if (!strcmp (attr->name, "nosave")) { + def->nosave = true; + } else { + warning (0, "skipping unknown attribute '%s'", attr->name); + } + } +} + void declare_def (specifier_t spec, const expr_t *init, symtab_t *symtab, expr_t *block) @@ -693,9 +706,7 @@ declare_def (specifier_t spec, const expr_t *init, symtab_t *symtab, } initialize_def (sym, init, space, spec.storage, symtab, block); - if (sym->def) { - sym->def->nosave |= spec.nosave; - } + set_def_attributes (sym->def, spec.attributes); } static int diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 27fbefd7c..bb1934bab 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -46,6 +46,7 @@ #include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/attribute.h" #include "tools/qfcc/include/class.h" #include "tools/qfcc/include/codespace.h" #include "tools/qfcc/include/debug.h" @@ -581,6 +582,21 @@ get_function (const char *name, const type_t *type, specifier_t spec) return func; } +static void +set_func_type_attrs (const type_t *func_type, attribute_t *attr_list) +{ + auto func = &((type_t *) func_type)->func;//FIXME + for (auto attr = attr_list; attr; attr = attr->next) { + if (!strcmp (attr->name, "no_va_list")) { + func->no_va_list = true; + } else if (!strcmp (attr->name, "void_return")) { + func->void_return = true; + } else { + warning (0, "skipping unknown function attribute '%s'", attr->name); + } + } +} + symbol_t * function_symbol (specifier_t spec) { @@ -611,7 +627,7 @@ function_symbol (specifier_t spec) 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); + set_func_type_attrs (spec.sym->type, spec.attributes); spec.sym->type = find_type (spec.sym->type); } func = get_function (name, unalias_type (sym->type), spec); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index ab9649064..da9a85019 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -319,24 +319,6 @@ generic_spec (void) return spec; } -static specifier_t -parse_attributes (attribute_t *attr_list) -{ - specifier_t spec = {}; - for (attribute_t *attr = attr_list; attr; attr = attr->next) { - if (!strcmp (attr->name, "no_va_list")) { - spec.no_va_list = true; - } else if (!strcmp (attr->name, "nosave")) { - spec.nosave = true; - } else if (!strcmp (attr->name, "void_return")) { - spec.void_return = true; - } else { - warning (0, "skipping unknown attribute '%s'", attr->name); - } - } - return spec; -} - static int storage_auto (specifier_t spec) { @@ -392,6 +374,12 @@ spec_merge (specifier_t spec, specifier_t new) spec.multi_store = true; } } + for (auto attr = &spec.attributes; *attr; attr = &(*attr)->next) { + if (!(*attr)->next) { + (*attr)->next = new.attributes; + break; + } + } spec.sym = new.sym; spec.spec_bits |= new.spec_bits; return spec; @@ -1205,7 +1193,7 @@ storage_class } | ATTRIBUTE '(' attribute_list ')' { - $$ = parse_attributes ($3); + $$ = (specifier_t) { .attributes = $3 }; } ; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index e11db8d19..3811c26c1 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -496,13 +496,6 @@ append_type (const type_t *type, const type_t *new) return type; } -void -set_func_type_attrs (const type_t *func, specifier_t spec) -{ - ((type_t *) func)->func.no_va_list = spec.no_va_list;//FIXME - ((type_t *) func)->func.void_return = spec.void_return; -} - specifier_t default_type (specifier_t spec, const symbol_t *sym) {