mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-07 18:01:30 +00:00
[qfcc] Rework function/pointer/array declarations
They should now work in generic contexts, but the pressing need to work on arrays was due to constant expressions for element counts breaking. As a side effect, function pointers are now a thing (and seem to work like they do in C)
This commit is contained in:
parent
fd836e74e1
commit
99632ddb03
18 changed files with 358 additions and 199 deletions
|
@ -6,10 +6,10 @@
|
|||
#include <script.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef void () void_function;
|
||||
typedef void (*void_function)();
|
||||
|
||||
int PR_SetField (entity ent, string field, string value) = #0;
|
||||
@function(void) PR_FindFunction (string func) = #0;
|
||||
void_function PR_FindFunction (string func) = #0;
|
||||
|
||||
@static void ParseEntities (string ent_data);
|
||||
|
||||
|
@ -80,7 +80,7 @@ int PR_SetField (entity ent, string field, string value) = #0;
|
|||
local int count;
|
||||
local string field, value;
|
||||
local plitem_t *keys;
|
||||
local @function(void) func;
|
||||
local void_function func;
|
||||
local Entity *e;
|
||||
|
||||
classname = PL_String (PL_ObjectForKey (dict, "classname"));
|
||||
|
|
|
@ -78,7 +78,7 @@ BOOL (id object) object_is_meta_class = #0;
|
|||
|
||||
@end
|
||||
|
||||
typedef void arIMP(id, SEL, id);
|
||||
typedef void (*arIMP)(id, SEL, id);
|
||||
|
||||
@static BOOL allocDebug;
|
||||
@static Class autoreleaseClass;
|
||||
|
|
|
@ -108,6 +108,7 @@ typedef struct element_chain_s {
|
|||
element_t *head;
|
||||
element_t **tail;
|
||||
const type_t *type; ///< inferred if null
|
||||
const expr_t *type_expr;
|
||||
} element_chain_t;
|
||||
|
||||
typedef struct ex_listitem_s {
|
||||
|
@ -1045,6 +1046,7 @@ expr_t *new_memset_expr (const expr_t *dst, const expr_t *val,
|
|||
const expr_t *count);
|
||||
|
||||
expr_t *new_type_expr (const type_t *type);
|
||||
expr_t *new_type_function (int op, const expr_t *params);
|
||||
const expr_t *type_function (int op, const expr_t *params);
|
||||
symbol_t *type_parameter (symbol_t *sym, const expr_t *type);
|
||||
const type_t *resolve_type (const expr_t *te, rua_ctx_t *ctx);
|
||||
|
@ -1156,6 +1158,7 @@ const expr_t *gather_factors (const type_t *type, int op,
|
|||
|
||||
typedef struct rua_ctx_s rua_ctx_t;
|
||||
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);
|
||||
|
||||
///@}
|
||||
|
|
|
@ -61,6 +61,7 @@ extern const char *storage_class_names[sc_count];
|
|||
typedef struct specifier_s {
|
||||
const type_t *type;
|
||||
const expr_t *type_expr;
|
||||
expr_t *type_list;
|
||||
attribute_t *attributes;
|
||||
param_t *params;
|
||||
symbol_t *sym;
|
||||
|
@ -80,7 +81,6 @@ typedef struct specifier_s {
|
|||
bool is_overload:1;
|
||||
bool is_generic:1;
|
||||
bool is_generic_block:1;
|
||||
bool is_function:1;//FIXME do proper void(*)() -> ev_func
|
||||
bool is_far:1;
|
||||
};
|
||||
unsigned spec_bits;
|
||||
|
|
|
@ -285,7 +285,8 @@ symbol_t *make_symbol (const char *name, const struct type_s *type,
|
|||
struct specifier_s;
|
||||
symbol_t *declare_symbol (struct specifier_s spec, const expr_t *init,
|
||||
symtab_t *symtab, expr_t *block, rua_ctx_t *ctx);
|
||||
symbol_t *declare_field (struct specifier_s spec, symtab_t *symtab);
|
||||
symbol_t *declare_field (struct specifier_s spec, symtab_t *symtab,
|
||||
rua_ctx_t *ctx);
|
||||
|
||||
///@}
|
||||
|
||||
|
|
|
@ -86,9 +86,8 @@ type_t type_SEL = {
|
|||
};
|
||||
const type_t *IMP_params[] = { &type_id, &type_SEL };
|
||||
param_qual_t IMP_quals[] = { pq_in, pq_in };
|
||||
type_t type_IMP = {
|
||||
type_t type_IMP_func = {
|
||||
.type = ev_func,
|
||||
.name = "IMP",
|
||||
.alignment = 1,
|
||||
.width = 1,
|
||||
.columns = 1,
|
||||
|
@ -101,6 +100,17 @@ type_t type_IMP = {
|
|||
.no_va_list = 1,
|
||||
},
|
||||
};
|
||||
type_t type_IMP = {
|
||||
.type = ev_ptr,
|
||||
.name = "IMP",
|
||||
.alignment = 1,
|
||||
.width = 1,
|
||||
.columns = 1,
|
||||
.meta = ty_basic,
|
||||
.fldptr = {
|
||||
.type = &type_IMP_func,
|
||||
},
|
||||
};
|
||||
type_t type_super = {
|
||||
.type = ev_invalid,
|
||||
};
|
||||
|
@ -1983,6 +1993,7 @@ init_objective_structs (void)
|
|||
make_structure ("obj_selector", 's', sel_struct, &type_selector);
|
||||
chain_type (&type_selector);
|
||||
chain_type (&type_SEL);
|
||||
chain_type (&type_IMP_func);
|
||||
chain_type (&type_IMP);
|
||||
|
||||
make_structure ("obj_method", 's', method_struct, &type_method);
|
||||
|
@ -2009,8 +2020,8 @@ init_objective_structs (void)
|
|||
static void
|
||||
init_classes (void)
|
||||
{
|
||||
make_structure ("obj_class", 's', class_struct, &type_class);
|
||||
chain_type (&type_class);
|
||||
make_structure ("obj_class", 's', class_struct, &type_class);
|
||||
chain_type (&type_Class);
|
||||
make_structure ("obj_object", 's', object_struct, &type_object);
|
||||
chain_type (&type_object);
|
||||
|
|
|
@ -106,6 +106,7 @@ get_op_string (int op)
|
|||
case QC_REVERSE: return "@reverse";
|
||||
case QC_DUAL: return "@dual";
|
||||
case QC_UNDUAL: return "@undual";
|
||||
case QC_AT_FUNCTION:return "@function";
|
||||
case QC_AT_FIELD: return "@field";
|
||||
case QC_AT_POINTER: return "@pointer";
|
||||
case QC_AT_ARRAY: return "@array";
|
||||
|
@ -342,7 +343,10 @@ print_type_expr (dstring_t *dstr, const expr_t *e, int level, int id,
|
|||
dasprintf (dstr, "%*se_%p -> e_%p;\n", indent, "", e, e->typ.params);
|
||||
str = get_op_string (e->typ.op);
|
||||
} else if (e->typ.type) {
|
||||
str = e->typ.type->encoding;
|
||||
str = e->typ.type->encoding;
|
||||
if (!str) {
|
||||
str = type_get_encoding (e->typ.type);
|
||||
}
|
||||
} else if (e->typ.sym) {
|
||||
str = e->typ.sym->name;
|
||||
}
|
||||
|
|
|
@ -459,7 +459,10 @@ function_expr (const expr_t *fexpr, const expr_t *args)
|
|||
}
|
||||
|
||||
auto ftype = get_type (fexpr);
|
||||
if (ftype->type != ev_func) {
|
||||
if (is_ptr (ftype) && is_func (dereference_type (ftype))) {
|
||||
ftype = dereference_type (ftype);
|
||||
}
|
||||
if (!is_func (ftype)) {
|
||||
if (fexpr->type == ex_symbol)
|
||||
return error (fexpr, "Called object \"%s\" is not a function",
|
||||
fexpr->symbol->name);
|
||||
|
|
|
@ -108,8 +108,12 @@ cast_expr (const type_t *dstType, const expr_t *e)
|
|||
}
|
||||
|
||||
if ((dstType == type_default && is_enum (srcType))
|
||||
|| (is_enum (dstType) && srcType == type_default))
|
||||
|| (is_enum (dstType) && srcType == type_default)) {
|
||||
return e;
|
||||
}
|
||||
if ((is_pointer (dstType) && is_func (srcType))) {
|
||||
return new_alias_expr (dstType, e);
|
||||
}
|
||||
if ((is_pointer (dstType) && is_string (srcType))
|
||||
|| (is_string (dstType) && is_pointer (srcType))) {
|
||||
return new_alias_expr (dstType, e);
|
||||
|
|
|
@ -50,14 +50,27 @@
|
|||
|
||||
typedef const expr_t *(*process_f) (const expr_t *expr, rua_ctx_t *ctx);
|
||||
|
||||
static const type_t *
|
||||
proc_decl_type (const expr_t *decl, rua_ctx_t *ctx)
|
||||
{
|
||||
if (decl->type != ex_decl) {
|
||||
internal_error (decl, "not a decl expression");
|
||||
}
|
||||
if (decl->decl.list.head) {
|
||||
internal_error (decl, "non-empty cast decl");
|
||||
}
|
||||
auto spec = spec_process (decl->decl.spec, ctx);
|
||||
return spec.type;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
proc_expr (const expr_t *expr, rua_ctx_t *ctx)
|
||||
{
|
||||
scoped_src_loc (expr);
|
||||
if (expr->expr.op == 'C') {
|
||||
auto type = resolve_type (expr->expr.e1, ctx);
|
||||
expr = expr_process (expr->expr.e2, ctx);
|
||||
return cast_expr (type, expr);
|
||||
auto type = proc_decl_type (expr->expr.e1, ctx);
|
||||
auto e = expr_process (expr->expr.e2, ctx);
|
||||
return cast_expr (type, e);
|
||||
}
|
||||
auto e1 = expr_process (expr->expr.e1, ctx);
|
||||
auto e2 = expr_process (expr->expr.e2, ctx);
|
||||
|
@ -447,6 +460,9 @@ proc_compound (const expr_t *expr, rua_ctx_t *ctx)
|
|||
{
|
||||
scoped_src_loc (expr);
|
||||
auto comp = new_compound_init ();
|
||||
if (expr->compound.type_expr) {
|
||||
comp->compound.type = proc_decl_type (expr->compound.type_expr, ctx);
|
||||
}
|
||||
for (auto ele = expr->compound.head; ele; ele = ele->next) {
|
||||
append_element (comp, new_element (expr_process (ele->expr, ctx),
|
||||
ele->designator));
|
||||
|
@ -593,18 +609,132 @@ proc_cond (const expr_t *expr, rua_ctx_t *ctx)
|
|||
return new_cond_expr (test, true_expr, false_expr);
|
||||
}
|
||||
|
||||
static const type_t *
|
||||
decl_function (const type_t *type, const expr_t *t, const symbol_t *sym,
|
||||
rua_ctx_t *ctx)
|
||||
{
|
||||
scoped_src_loc (t);
|
||||
if (type && is_func (type)) {
|
||||
error (t, "'%s' declared as a function returning a function",
|
||||
sym->name);
|
||||
} else if (type && is_array (type)) {
|
||||
error (t, "'%s' declared as function returning an array", sym->name);
|
||||
}
|
||||
// FIXME not sure I like this setup for @function
|
||||
auto params = t->typ.params;
|
||||
auto ftype = params->typ.type;
|
||||
if (type) {
|
||||
ftype = append_type (ftype, type);
|
||||
ftype = find_type (ftype);
|
||||
}
|
||||
return ftype;
|
||||
}
|
||||
|
||||
static const type_t *
|
||||
decl_array (const type_t *type, const expr_t *t, const symbol_t *sym,
|
||||
rua_ctx_t *ctx)
|
||||
{
|
||||
scoped_src_loc (t);
|
||||
if (type && is_func (type)) {
|
||||
error (t, "declaration of '%s' as array of functions", sym->name);
|
||||
}
|
||||
auto params = new_list_expr (nullptr);
|
||||
if (!proc_do_list (¶ms->list, &t->typ.params->list, ctx)) {
|
||||
return type;
|
||||
}
|
||||
expr_prepend_expr (params, new_type_expr (type));
|
||||
auto type_expr = type_function (QC_AT_ARRAY, params);
|
||||
return resolve_type (type_expr, ctx);
|
||||
}
|
||||
|
||||
static const type_t *
|
||||
decl_pointer (const type_t *type, const expr_t *t, const symbol_t *sym,
|
||||
rua_ctx_t *ctx)
|
||||
{
|
||||
scoped_src_loc (t);
|
||||
auto params = new_list_expr (new_type_expr (type));
|
||||
auto type_expr = type_function (QC_AT_POINTER, params);
|
||||
return resolve_type (type_expr, ctx);
|
||||
}
|
||||
|
||||
static const type_t *
|
||||
decl_field (const type_t *type, const expr_t *t, const symbol_t *sym,
|
||||
rua_ctx_t *ctx)
|
||||
{
|
||||
scoped_src_loc (t);
|
||||
auto params = new_list_expr (new_type_expr (type));
|
||||
auto type_expr = type_function (QC_AT_FIELD, params);
|
||||
return resolve_type (type_expr, ctx);
|
||||
}
|
||||
|
||||
specifier_t
|
||||
spec_process (specifier_t spec, rua_ctx_t *ctx)
|
||||
{
|
||||
if (spec.type && spec.type_expr) {
|
||||
internal_error (0, "both type and type_expr set");
|
||||
}
|
||||
if (!spec.type_expr) {
|
||||
spec = default_type (spec, spec.sym);
|
||||
}
|
||||
if (!spec.type_list) {
|
||||
return spec;
|
||||
}
|
||||
if (spec.type_list->type != ex_list) {
|
||||
internal_error (spec.type_list, "not a list");
|
||||
}
|
||||
int num_types = list_count (&spec.type_list->list);
|
||||
const expr_t *type_list[num_types];
|
||||
auto type = spec.type; // core type (int etc)
|
||||
if (spec.type_expr) {
|
||||
type = resolve_type (spec.type_expr, ctx);
|
||||
}
|
||||
//const type_t *type = nullptr;
|
||||
// other than fields, the type list is built up by appending types
|
||||
// to the list, but it's the final type in the list that takes the
|
||||
// core type, so extract them in reverse for a forward loop
|
||||
list_scatter_rev (&spec.type_list->list, type_list);
|
||||
for (int i = 0; i < num_types; i++) {
|
||||
auto t = type_list[i];
|
||||
if (t->type != ex_type) {
|
||||
internal_error (t, "not a type expr");
|
||||
}
|
||||
switch (t->typ.op) {
|
||||
case QC_AT_FUNCTION:
|
||||
type = decl_function (type, t, spec.sym, ctx);
|
||||
break;
|
||||
case QC_AT_ARRAY:
|
||||
type = decl_array (type, t, spec.sym, ctx);
|
||||
break;
|
||||
case QC_AT_POINTER:
|
||||
type = decl_pointer (type, t, spec.sym, ctx);
|
||||
break;
|
||||
case QC_AT_FIELD:
|
||||
type = decl_field (type, t, spec.sym, ctx);
|
||||
break;
|
||||
default:
|
||||
internal_error (t, "unexpected type op: %d", t->typ.op);
|
||||
}
|
||||
}
|
||||
spec.type_list = nullptr;
|
||||
spec.type = type;
|
||||
return spec;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
proc_decl (const expr_t *expr, rua_ctx_t *ctx)
|
||||
{
|
||||
scoped_src_loc (expr);
|
||||
expr_t *block = nullptr;
|
||||
auto decl_spec = expr->decl.spec;
|
||||
if (decl_spec.type && decl_spec.type_expr) {
|
||||
internal_error (0, "both type and type_expr set");
|
||||
}
|
||||
if (decl_spec.storage == sc_local) {
|
||||
scoped_src_loc (expr);
|
||||
block = new_block_expr (nullptr);
|
||||
}
|
||||
int count = list_count (&expr->decl.list);
|
||||
const expr_t *decls[count + 1];
|
||||
const expr_t *decls[count];
|
||||
list_scatter (&expr->decl.list, decls);
|
||||
for (int i = 0; i < count; i++) {
|
||||
auto decl = decls[i];
|
||||
|
@ -628,6 +758,12 @@ proc_decl (const expr_t *expr, rua_ctx_t *ctx)
|
|||
internal_error (decl, "not a symbol");
|
||||
}
|
||||
auto spec = decl_spec;
|
||||
spec.sym = sym;
|
||||
if (spec.type_list) {
|
||||
// to get here, a concrete declaration is being made
|
||||
spec.is_generic = false;
|
||||
spec = spec_process (spec, ctx);
|
||||
}
|
||||
if (sym && !spec.type_expr) {
|
||||
spec.type = append_type (sym->type, spec.type);
|
||||
spec.type = find_type (spec.type);
|
||||
|
|
|
@ -161,6 +161,7 @@ single_type_opt_int_pair (int arg_count, const expr_t **args)
|
|||
static const expr_t *
|
||||
evaluate_int (const expr_t *expr, rua_ctx_t *ctx)
|
||||
{
|
||||
expr = expr_process (expr, ctx);
|
||||
if (expr->type == ex_expr || expr->type == ex_uexpr) {
|
||||
auto e = new_expr ();
|
||||
*e = *expr;
|
||||
|
@ -203,7 +204,7 @@ resolve_function (int arg_count, const expr_t **args, rua_ctx_t *ctx)
|
|||
return &type_func;//FIXME
|
||||
auto type = resolve_type (args[0], ctx);
|
||||
if (type) {
|
||||
type = field_type (type);
|
||||
type = field_type (type);//FIXME wrong type
|
||||
type = find_type (type);
|
||||
}
|
||||
return type;
|
||||
|
@ -224,10 +225,7 @@ static const type_t *
|
|||
resolve_pointer (int arg_count, const expr_t **args, rua_ctx_t *ctx)
|
||||
{
|
||||
auto type = resolve_type (args[0], ctx);
|
||||
if (type) {
|
||||
type = pointer_type (type);
|
||||
type = find_type (type);
|
||||
}
|
||||
type = pointer_type (type);
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -235,17 +233,15 @@ static const type_t *
|
|||
resolve_array (int arg_count, const expr_t **args, rua_ctx_t *ctx)
|
||||
{
|
||||
auto type = resolve_type (args[0], ctx);
|
||||
if (type) {
|
||||
int count = 0;
|
||||
if (arg_count > 1) {
|
||||
auto count_expr = evaluate_int (args[1], ctx);
|
||||
if (is_error (count_expr)) {
|
||||
return nullptr;
|
||||
}
|
||||
count = expr_int (count_expr);
|
||||
int count = 0;
|
||||
if (arg_count > 1) {
|
||||
auto count_expr = evaluate_int (args[1], ctx);
|
||||
if (is_error (count_expr)) {
|
||||
return nullptr;
|
||||
}
|
||||
type = array_type (type, count);
|
||||
count = expr_integral (count_expr);
|
||||
}
|
||||
type = array_type (type, count);
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -671,6 +667,19 @@ static type_func_t type_funcs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
expr_t *
|
||||
new_type_function (int op, const expr_t *params)
|
||||
{
|
||||
auto te = new_expr ();
|
||||
te->type = ex_type;
|
||||
te->nodag = true;
|
||||
te->typ = (ex_type_t) {
|
||||
.op = op,
|
||||
.params = params,
|
||||
};
|
||||
return te;
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
type_function (int op, const expr_t *params)
|
||||
{
|
||||
|
@ -686,14 +695,7 @@ type_function (int op, const expr_t *params)
|
|||
if (msg) {
|
||||
return error (params, "%s for %s", msg, type_funcs[ind].name);
|
||||
}
|
||||
auto te = new_expr ();
|
||||
te->type = ex_type;
|
||||
te->nodag = true;
|
||||
te->typ = (ex_type_t) {
|
||||
.op = op,
|
||||
.params = params,
|
||||
};
|
||||
return te;
|
||||
return new_type_function (op, params);
|
||||
}
|
||||
|
||||
symbol_t *
|
||||
|
@ -725,9 +727,9 @@ resolve_type (const expr_t *te, rua_ctx_t *ctx)
|
|||
internal_error (te, "not a type expression");
|
||||
}
|
||||
if (!te->typ.op) {
|
||||
if (!te->typ.type) {
|
||||
internal_error (te, "no type in reference");
|
||||
}
|
||||
//if (!te->typ.type) {
|
||||
// internal_error (te, "no type in reference");
|
||||
//}
|
||||
return te->typ.type;
|
||||
}
|
||||
int op = te->typ.op;
|
||||
|
|
|
@ -755,11 +755,11 @@ create_generic_sym (genfunc_t *g, const expr_t *fexpr, calltype_t *calltype,
|
|||
}
|
||||
|
||||
static metafunc_t *
|
||||
get_function (const char *name, specifier_t spec)
|
||||
get_function (const char *name, specifier_t spec, rua_ctx_t *ctx)
|
||||
{
|
||||
if (!spec.sym->type || !spec.sym->type->encoding) {
|
||||
spec = default_type (spec, spec.sym);
|
||||
spec.sym->type = append_type (spec.sym->type, spec.type);
|
||||
spec = spec_process (spec, ctx);
|
||||
spec.sym->type = spec.type;
|
||||
set_func_attrs (spec.sym->type, spec.attributes);
|
||||
spec.sym->type = find_type (spec.sym->type);
|
||||
}
|
||||
|
@ -850,6 +850,7 @@ symbol_t *
|
|||
function_symbol (specifier_t spec, rua_ctx_t *ctx)
|
||||
{
|
||||
symbol_t *sym = spec.sym;
|
||||
sym->params = spec.params;
|
||||
const char *name = sym->name;
|
||||
metafunc_t *func = Hash_Find (function_map, name);
|
||||
|
||||
|
@ -879,7 +880,7 @@ function_symbol (specifier_t spec, rua_ctx_t *ctx)
|
|||
Hash_Add (metafuncs, func);
|
||||
Hash_Add (function_map, func);
|
||||
} else {
|
||||
func = get_function (name, spec);
|
||||
func = get_function (name, spec, ctx);
|
||||
}
|
||||
|
||||
if (func && func->meta_type == mf_overload)
|
||||
|
|
|
@ -108,6 +108,6 @@ void
|
|||
glsl_declare_field (specifier_t spec, symtab_t *symtab, rua_ctx_t *ctx)
|
||||
{
|
||||
auto attributes = glsl_optimize_attributes (spec.attributes);
|
||||
spec.sym = declare_field (spec, symtab);
|
||||
spec.sym = declare_field (spec, symtab, ctx);
|
||||
glsl_apply_attributes (attributes, spec);
|
||||
}
|
||||
|
|
|
@ -359,7 +359,7 @@ send_message (int super, rua_ctx_t *ctx)
|
|||
{
|
||||
symbol_t *sym;
|
||||
const char *sm_name = "obj_msgSend";
|
||||
type_t *sm_type = &type_IMP;
|
||||
const type_t *sm_type = type_IMP.fldptr.type;
|
||||
|
||||
if (super) {
|
||||
sm_name = "obj_msgSend_super";
|
||||
|
|
|
@ -199,7 +199,7 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
|
|||
%type <spec> enum_specifier algebra_specifier
|
||||
%type <symbol> optional_enum_list enum_list enumerator_list enumerator
|
||||
%type <symbol> enum_init
|
||||
%type <size> array_decl
|
||||
%type <expr> array_decl
|
||||
|
||||
%type <expr> const string
|
||||
|
||||
|
@ -213,7 +213,7 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
|
|||
%type <expr> opt_init_semi opt_expr comma_expr
|
||||
%type <expr> expr
|
||||
%type <expr> compound_init
|
||||
%type <spec> opt_cast
|
||||
%type <expr> opt_cast
|
||||
%type <mut_expr> element_list expr_list
|
||||
%type <designator> designator designator_spec
|
||||
%type <element> element
|
||||
|
@ -353,6 +353,7 @@ spec_merge (specifier_t spec, specifier_t new)
|
|||
spec.multi_type = true;
|
||||
}
|
||||
}
|
||||
spec.type_list = new.type_list;
|
||||
if (new.is_typedef || !storage_auto (new)) {
|
||||
if ((spec.is_typedef || !storage_auto (spec)) && !spec.multi_store) {
|
||||
error (0, "multiple storage classes in declaration specifiers");
|
||||
|
@ -391,50 +392,40 @@ spec_merge (specifier_t spec, specifier_t new)
|
|||
return spec;
|
||||
}
|
||||
|
||||
static const type_t *
|
||||
static specifier_t
|
||||
resolve_type_spec (specifier_t spec, rua_ctx_t *ctx)
|
||||
{
|
||||
spec = spec_process (spec, ctx);
|
||||
auto type = spec.type;
|
||||
if (spec.type_expr) {
|
||||
type = resolve_type (spec.type_expr, ctx);
|
||||
spec.type_expr = nullptr;
|
||||
}
|
||||
return find_type (type);
|
||||
}
|
||||
|
||||
static specifier_t
|
||||
typename_spec (specifier_t spec)
|
||||
{
|
||||
spec = default_type (spec, 0);
|
||||
spec.sym->type = find_type (append_type (spec.sym->type, spec.type));
|
||||
spec.type = spec.sym->type;
|
||||
spec.type = find_type (type);
|
||||
return spec;
|
||||
}
|
||||
|
||||
static specifier_t
|
||||
function_spec (specifier_t spec, param_t *params)
|
||||
typename_spec (specifier_t spec, rua_ctx_t *ctx)
|
||||
{
|
||||
// empty param list in an abstract decl does not create a symbol
|
||||
if (!spec.sym) {
|
||||
spec.sym = new_symbol (0);
|
||||
spec = default_type (spec, 0);
|
||||
return spec;
|
||||
}
|
||||
|
||||
static specifier_t
|
||||
function_spec (specifier_t spec, param_t *parameters)
|
||||
{
|
||||
// return type will be filled in when building the final type
|
||||
// FIXME not sure I like this setup for @function
|
||||
auto params = new_type_expr (parse_params (0, parameters));
|
||||
auto type_expr = new_type_function (QC_AT_FUNCTION, params);
|
||||
if (spec.type_list) {
|
||||
expr_append_expr (spec.type_list, type_expr);
|
||||
} else {
|
||||
spec.type_list = new_list_expr (type_expr);
|
||||
}
|
||||
if (!spec.type_expr) {
|
||||
spec = default_type (spec, spec.sym);
|
||||
}
|
||||
spec.sym->params = params;
|
||||
if (spec.sym->type) {
|
||||
if (is_func (spec.sym->type)) {
|
||||
error (0, "'%s' declared as a function returning a function",
|
||||
spec.sym->name);
|
||||
} else if (is_array (spec.sym->type)) {
|
||||
error (0, "declaration of '%s' as array of functions",
|
||||
spec.sym->name);
|
||||
} else if (!is_pointer (spec.sym->type)
|
||||
&& !is_field (spec.sym->type)) {
|
||||
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.params = parameters;
|
||||
spec.is_generic = generic_scope;
|
||||
spec.is_generic_block = generic_block;
|
||||
spec.symtab = generic_symtab;
|
||||
|
@ -442,41 +433,50 @@ function_spec (specifier_t spec, param_t *params)
|
|||
}
|
||||
|
||||
static specifier_t
|
||||
array_spec (specifier_t spec, unsigned size)
|
||||
array_spec (specifier_t spec, const expr_t *size)
|
||||
{
|
||||
spec = default_type (spec, spec.sym);
|
||||
if (spec.sym->type) {
|
||||
if (is_func (spec.sym->type)) {
|
||||
error (0, "'%s' declared as function returning an array",
|
||||
spec.sym->name);
|
||||
} else if (!is_pointer (spec.sym->type)
|
||||
&& !is_array (spec.sym->type)
|
||||
&& !is_field (spec.sym->type)) {
|
||||
internal_error (0, "unexpected type");
|
||||
}
|
||||
// element type will be filled in when building the final type
|
||||
auto params = new_list_expr (size);
|
||||
auto type_expr = new_type_function (QC_AT_ARRAY, params);
|
||||
if (spec.type_list) {
|
||||
expr_append_expr (spec.type_list, type_expr);
|
||||
} else {
|
||||
spec.type_list = new_list_expr (type_expr);
|
||||
}
|
||||
spec.sym->type = append_type (spec.sym->type, array_type (0, size));
|
||||
return spec;
|
||||
}
|
||||
|
||||
static specifier_t
|
||||
pointer_spec (specifier_t quals, specifier_t spec)
|
||||
{
|
||||
if (spec.sym->type) {
|
||||
if (!is_func (spec.sym->type)
|
||||
&& !is_pointer (spec.sym->type)
|
||||
&& !is_array (spec.sym->type)
|
||||
&& !is_field (spec.sym->type)) {
|
||||
internal_error (0, "unexpected type");
|
||||
}
|
||||
// referenced type will be filled in when building the final type
|
||||
auto type_expr = new_type_function (QC_AT_POINTER, nullptr);
|
||||
if (spec.type_list) {
|
||||
expr_append_expr (spec.type_list, type_expr);
|
||||
} else {
|
||||
spec.type_list = new_list_expr (type_expr);
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
||||
static specifier_t
|
||||
field_spec (specifier_t spec)
|
||||
{
|
||||
// referenced type will be filled in when building the final type
|
||||
auto type_expr = new_type_function (QC_AT_FIELD, nullptr);
|
||||
if (spec.type_list) {
|
||||
expr_prepend_expr (spec.type_list, type_expr);
|
||||
} else {
|
||||
spec.type_list = new_list_expr (type_expr);
|
||||
}
|
||||
spec.sym->type = append_type (spec.sym->type, pointer_type (0));
|
||||
return spec;
|
||||
}
|
||||
|
||||
static specifier_t
|
||||
qc_function_spec (specifier_t spec, param_t *params)
|
||||
{
|
||||
#if 0
|
||||
//FIXME this is borked
|
||||
// .float () foo; is a field holding a function variable rather
|
||||
// than a function that returns a float field.
|
||||
// FIXME I think this breaks fields holding functions that return fields
|
||||
|
@ -494,19 +494,17 @@ qc_function_spec (specifier_t spec, param_t *params)
|
|||
spec.sym = new_symbol (0);
|
||||
spec.sym->type = field_chain;
|
||||
spec.type = ret_type;
|
||||
#endif
|
||||
|
||||
spec = function_spec (spec, params);
|
||||
return spec;
|
||||
}
|
||||
|
||||
static specifier_t
|
||||
qc_set_symbol (specifier_t spec, symbol_t *sym)
|
||||
qc_set_symbol (specifier_t spec, symbol_t *sym, rua_ctx_t *ctx)
|
||||
{
|
||||
// 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 = spec_process (spec, ctx);
|
||||
sym->type = spec.type;
|
||||
spec.sym = sym;
|
||||
return spec;
|
||||
}
|
||||
|
@ -518,20 +516,25 @@ make_ellipsis (void)
|
|||
}
|
||||
|
||||
static param_t *
|
||||
make_param (specifier_t spec)
|
||||
make_param (specifier_t spec, rua_ctx_t *ctx)
|
||||
{
|
||||
//FIXME should not be sc_global
|
||||
if (spec.storage == sc_global) {
|
||||
spec.storage = sc_param;
|
||||
}
|
||||
|
||||
spec = spec_process (spec, ctx);
|
||||
|
||||
param_t *param;
|
||||
if (spec.type_expr) {
|
||||
param = new_generic_param (spec.type_expr, spec.sym->name);
|
||||
} else {
|
||||
} else if (spec.sym) {
|
||||
spec = default_type (spec, spec.sym);
|
||||
spec.type = find_type (append_type (spec.sym->type, spec.type));
|
||||
param = new_param (0, spec.type, spec.sym->name);
|
||||
param = new_param (nullptr, spec.type, spec.sym->name);
|
||||
} else {
|
||||
spec = default_type (spec, spec.sym);
|
||||
param = new_param (nullptr, spec.type, nullptr);
|
||||
}
|
||||
if (spec.is_const) {
|
||||
if (spec.storage == sc_out) {
|
||||
|
@ -569,19 +572,20 @@ make_selector (const char *selector, const type_t *type, const char *name)
|
|||
}
|
||||
|
||||
static param_t *
|
||||
make_qc_param (specifier_t spec, symbol_t *sym)
|
||||
make_qc_param (specifier_t spec, symbol_t *sym, rua_ctx_t *ctx)
|
||||
{
|
||||
sym->type = nullptr;
|
||||
spec.sym = sym;
|
||||
return make_param (spec);
|
||||
return make_param (spec, ctx);
|
||||
}
|
||||
|
||||
static param_t *
|
||||
make_qc_func_param (specifier_t spec, param_t *params, symbol_t *sym)
|
||||
make_qc_func_param (specifier_t spec, param_t *params, symbol_t *sym,
|
||||
rua_ctx_t *ctx)
|
||||
{
|
||||
spec = qc_function_spec (spec, params);
|
||||
sym->type = append_type (spec.sym->type, spec.type);
|
||||
param_t *param = new_param (0, sym->type, sym->name);
|
||||
spec = spec_process (spec, ctx);
|
||||
param_t *param = new_param (0, spec.type, sym->name);
|
||||
return param;
|
||||
}
|
||||
|
||||
|
@ -795,11 +799,11 @@ qc_param_list
|
|||
qc_first_param
|
||||
: typespec identifier
|
||||
{
|
||||
$$ = make_qc_param ($1, $2);
|
||||
$$ = make_qc_param ($1, $2, ctx);
|
||||
}
|
||||
| typespec_reserved qc_func_params identifier
|
||||
{
|
||||
$$ = make_qc_func_param ($1, $2, $3);
|
||||
$$ = make_qc_func_param ($1, $2, $3, ctx);
|
||||
}
|
||||
| ELLIPSIS
|
||||
{
|
||||
|
@ -813,11 +817,11 @@ qc_first_param
|
|||
qc_param
|
||||
: typespec identifier
|
||||
{
|
||||
$$ = make_qc_param ($1, $2);
|
||||
$$ = make_qc_param ($1, $2, ctx);
|
||||
}
|
||||
| typespec qc_func_params identifier
|
||||
{
|
||||
$$ = make_qc_func_param ($1, $2, $3);
|
||||
$$ = make_qc_func_param ($1, $2, $3, ctx);
|
||||
}
|
||||
| ELLIPSIS
|
||||
{
|
||||
|
@ -859,7 +863,7 @@ qc_func_decl
|
|||
qc_nocode_func
|
||||
: identifier '=' '#' expr
|
||||
{
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1, ctx);
|
||||
const expr_t *bi_val = expr_process ($4, ctx);
|
||||
|
||||
spec.is_overload |= ctx->language->always_overload;
|
||||
|
@ -868,19 +872,19 @@ qc_nocode_func
|
|||
}
|
||||
| identifier '=' intrinsic
|
||||
{
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1, ctx);
|
||||
build_intrinsic_function (spec, $3, ctx);
|
||||
}
|
||||
| identifier '=' expr
|
||||
{
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1, ctx);
|
||||
const expr_t *expr = $3;
|
||||
|
||||
declare_symbol (spec, expr, current_symtab, local_expr, ctx);
|
||||
}
|
||||
| identifier
|
||||
{
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1, ctx);
|
||||
declare_symbol (spec, nullptr, current_symtab, local_expr, ctx);
|
||||
}
|
||||
;
|
||||
|
@ -889,7 +893,7 @@ qc_code_func
|
|||
: identifier '=' optional_state_expr
|
||||
save_storage
|
||||
{
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
||||
specifier_t spec = qc_set_symbol ($<spec>0, $1, ctx);
|
||||
auto fs = (funcstate_t) {
|
||||
.function = current_func,
|
||||
};
|
||||
|
@ -971,8 +975,9 @@ notype_declarator
|
|||
}
|
||||
| NAME
|
||||
{
|
||||
$$ = $<spec>0;
|
||||
$$.sym = new_symbol ($1->name);
|
||||
auto spec = $<spec>0;
|
||||
spec.sym = new_symbol ($1->name);
|
||||
$$ = spec;
|
||||
}
|
||||
| NOT
|
||||
{
|
||||
|
@ -1134,9 +1139,7 @@ typespec_reserved
|
|||
// for basic types, but functions need special treatment
|
||||
| '.' typespec_reserved
|
||||
{
|
||||
// avoid find_type()
|
||||
$$ = type_spec (field_type (0));
|
||||
$$.type = append_type ($$.type, $2.type);
|
||||
$$ = field_spec ($2);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1178,9 +1181,7 @@ typespec_nonreserved
|
|||
// for basic types, but functions need special treatment
|
||||
| '.' typespec_nonreserved
|
||||
{
|
||||
// avoid find_type()
|
||||
$$ = type_spec (field_type (0));
|
||||
$$.type = append_type ($$.type, $2.type);
|
||||
$$ = field_spec ($2);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1202,10 +1203,7 @@ save_storage
|
|||
function_body
|
||||
: method_optional_state_expr[state]
|
||||
{
|
||||
specifier_t spec = $<spec>0;
|
||||
if (!spec.is_generic) {
|
||||
spec = default_type (spec, spec.sym);
|
||||
}
|
||||
specifier_t spec = spec_process ($<spec>0, ctx);
|
||||
spec.is_overload |= ctx->language->always_overload;
|
||||
spec.sym = function_symbol (spec, ctx);
|
||||
$<spec>$ = spec;
|
||||
|
@ -1231,7 +1229,7 @@ function_body
|
|||
}
|
||||
| '=' '#' expr ';'
|
||||
{
|
||||
specifier_t spec = $<spec>0;
|
||||
specifier_t spec = spec_process ($<spec>0, ctx);
|
||||
const expr_t *bi_val = expr_process ($3, ctx);
|
||||
|
||||
spec.is_overload |= ctx->language->always_overload;
|
||||
|
@ -1240,7 +1238,7 @@ function_body
|
|||
}
|
||||
| '=' intrinsic
|
||||
{
|
||||
specifier_t spec = $<spec>0;
|
||||
specifier_t spec = spec_process ($<spec>0, ctx);
|
||||
build_intrinsic_function (spec, $2, ctx);
|
||||
}
|
||||
;
|
||||
|
@ -1300,7 +1298,7 @@ generic_type
|
|||
;
|
||||
|
||||
type_function
|
||||
: type_func '(' type_param_list ')' { $$ = type_function ($1, $3); }
|
||||
: type_func '(' type_param_list ')' { $$ = new_type_function ($1, $3); }
|
||||
;
|
||||
|
||||
type_func
|
||||
|
@ -1579,7 +1577,7 @@ components
|
|||
component_declarator
|
||||
: declarator
|
||||
{
|
||||
declare_field ($1, current_symtab);
|
||||
declare_field ($1, current_symtab, ctx);
|
||||
}
|
||||
| declarator ':' expr
|
||||
| ':' expr
|
||||
|
@ -1630,23 +1628,23 @@ parameter_list
|
|||
parameter
|
||||
: declspecs_ts param_declarator
|
||||
{
|
||||
$$ = make_param ($2);
|
||||
$$ = make_param ($2, ctx);
|
||||
}
|
||||
| declspecs_ts notype_declarator
|
||||
{
|
||||
$$ = make_param ($2);
|
||||
$$ = make_param ($2, ctx);
|
||||
}
|
||||
| declspecs_ts absdecl
|
||||
{
|
||||
$$ = make_param ($2);
|
||||
$$ = make_param ($2, ctx);
|
||||
}
|
||||
| declspecs_nosc_nots notype_declarator
|
||||
{
|
||||
$$ = make_param ($2);
|
||||
$$ = make_param ($2, ctx);
|
||||
}
|
||||
| declspecs_nosc_nots absdecl
|
||||
{
|
||||
$$ = make_param ($2);
|
||||
$$ = make_param ($2, ctx);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1654,7 +1652,6 @@ absdecl
|
|||
: /* empty */
|
||||
{
|
||||
$$ = $<spec>0;
|
||||
$$.sym = new_symbol (0);
|
||||
}
|
||||
| absdecl1
|
||||
;
|
||||
|
@ -1716,24 +1713,11 @@ param_declarator_nostarttypename
|
|||
;
|
||||
|
||||
typename
|
||||
: declspecs_nosc absdecl
|
||||
{
|
||||
$$ = typename_spec ($2);
|
||||
}
|
||||
: declspecs_nosc absdecl { $$ = typename_spec ($2, ctx); }
|
||||
;
|
||||
|
||||
array_decl
|
||||
: '[' expr ']'
|
||||
{
|
||||
if (is_int_val ($2) && expr_int ($2) > 0) {
|
||||
$$ = expr_int ($2);
|
||||
} else if (is_uint_val ($2) && expr_uint ($2) > 0) {
|
||||
$$ = expr_uint ($2);
|
||||
} else {
|
||||
error (0, "invalid array size");
|
||||
$$ = 0;
|
||||
}
|
||||
}
|
||||
: '[' expr ']' { $$ = $expr; }
|
||||
| '[' ']' { $$ = 0; }
|
||||
;
|
||||
|
||||
|
@ -1780,16 +1764,16 @@ var_initializer
|
|||
compound_init
|
||||
: opt_cast '{' element_list optional_comma '}'
|
||||
{
|
||||
auto type = resolve_type_spec ($1, ctx);
|
||||
$3->compound.type = type;
|
||||
auto cast = $1;
|
||||
$3->compound.type_expr = cast;
|
||||
$$ = $3;
|
||||
}
|
||||
| opt_cast '{' '}'
|
||||
{
|
||||
auto type = resolve_type_spec ($1, ctx);
|
||||
if (type) {
|
||||
auto cast = $1;
|
||||
if (cast) {
|
||||
auto elements = new_compound_init ();
|
||||
elements->compound.type = type;
|
||||
elements->compound.type_expr = cast;
|
||||
$$ = elements;
|
||||
} else {
|
||||
$$ = nullptr;
|
||||
|
@ -1798,8 +1782,8 @@ compound_init
|
|||
;
|
||||
|
||||
opt_cast
|
||||
: '(' typename ')' { $$ = $2; }
|
||||
| /*empty*/ { $$ = (specifier_t) {}; }
|
||||
: '(' typename ')' { $$ = new_decl_expr ($2, nullptr); }
|
||||
| /*empty*/ { $$ = nullptr; }
|
||||
;
|
||||
|
||||
method_optional_state_expr
|
||||
|
@ -2156,11 +2140,8 @@ cast_expr
|
|||
: '(' typename ')' cast_expr
|
||||
{
|
||||
auto spec = $2;
|
||||
auto type_expr = spec.type_expr;
|
||||
if (!type_expr) {
|
||||
type_expr = new_type_expr (spec.type);
|
||||
}
|
||||
$$ = new_binary_expr ('C', type_expr, $4);
|
||||
auto decl = new_decl_expr (spec, nullptr);
|
||||
$$ = new_binary_expr ('C', decl, $4);
|
||||
}
|
||||
| CONSTRUCT '(' typename ',' expr_list[args] ')' //FIXME arg_expr instead?
|
||||
{
|
||||
|
@ -2635,7 +2616,7 @@ notype_ivars
|
|||
ivar_declarator
|
||||
: declarator
|
||||
{
|
||||
declare_field ($1, current_symtab);
|
||||
declare_field ($1, current_symtab, ctx);
|
||||
}
|
||||
| declarator ':' expr
|
||||
| ':' expr
|
||||
|
@ -2747,15 +2728,15 @@ methodproto
|
|||
methoddecl
|
||||
: '(' typename ')' unaryselector
|
||||
{
|
||||
auto type = resolve_type_spec ($2, ctx);
|
||||
$$ = new_method (type, $4, 0);
|
||||
auto spec = resolve_type_spec ($2, ctx);
|
||||
$$ = new_method (spec.type, $4, 0);
|
||||
}
|
||||
| unaryselector
|
||||
{ $$ = new_method (&type_id, $1, 0); }
|
||||
| '(' typename ')' keywordselector optional_param_list
|
||||
{
|
||||
auto type = resolve_type_spec ($2, ctx);
|
||||
$$ = new_method (type, $4, $5);
|
||||
auto spec = resolve_type_spec ($2, ctx);
|
||||
$$ = new_method (spec.type, $4, $5);
|
||||
}
|
||||
| keywordselector optional_param_list
|
||||
{ $$ = new_method (&type_id, $1, $2); }
|
||||
|
@ -2810,18 +2791,22 @@ reserved_word
|
|||
keyworddecl
|
||||
: selector ':' '(' typename ')' identifier
|
||||
{
|
||||
auto type = resolve_type_spec ($4, ctx);
|
||||
$$ = make_selector ($1->name, type, $6->name);
|
||||
auto spec = resolve_type_spec ($4, ctx);
|
||||
$$ = make_selector ($1->name, spec.type, $6->name);
|
||||
}
|
||||
| selector ':' identifier
|
||||
{ $$ = make_selector ($1->name, &type_id, $3->name); }
|
||||
{
|
||||
$$ = make_selector ($1->name, &type_id, $3->name);
|
||||
}
|
||||
| ':' '(' typename ')' identifier
|
||||
{
|
||||
auto type = resolve_type_spec ($3, ctx);
|
||||
$$ = make_selector ("", type, $5->name);
|
||||
auto spec = resolve_type_spec ($3, ctx);
|
||||
$$ = make_selector ("", spec.type, $5->name);
|
||||
}
|
||||
| ':' identifier
|
||||
{ $$ = make_selector ("", &type_id, $2->name); }
|
||||
{
|
||||
$$ = make_selector ("", &type_id, $2->name);
|
||||
}
|
||||
;
|
||||
|
||||
obj_expr
|
||||
|
@ -2830,8 +2815,8 @@ obj_expr
|
|||
| PROTOCOL '(' identifier ')' { $$ = protocol_expr ($3->name); }
|
||||
| ENCODE '(' typename ')'
|
||||
{
|
||||
auto type = resolve_type_spec ($3, ctx);
|
||||
$$ = encode_expr (type);
|
||||
auto spec = resolve_type_spec ($3, ctx);
|
||||
$$ = encode_expr (spec.type);
|
||||
}
|
||||
| obj_string /* FIXME string object? */
|
||||
;
|
||||
|
|
|
@ -214,10 +214,9 @@ function_decl (symbol_t *sym, param_t *params, const type_t *ret_type,
|
|||
// use `@name` so `main` can be used (`.main` is reserved for the entry
|
||||
// point)
|
||||
auto fsym = new_symbol (va (0, "@%s", sym->name));
|
||||
fsym->params = params;
|
||||
fsym->type = parse_params (ret_type, params);
|
||||
fsym->type = find_type (fsym->type);
|
||||
fsym = function_symbol ((specifier_t) { .sym = fsym, }, ctx);
|
||||
fsym = function_symbol ((specifier_t) {.sym = fsym, .params = params}, ctx);
|
||||
auto fsym_expr = new_symbol_expr (fsym);
|
||||
if (!params) {
|
||||
fsym_expr = new_call_expr (fsym_expr, nullptr, nullptr);
|
||||
|
|
|
@ -291,16 +291,12 @@ declare_symbol (specifier_t spec, const expr_t *init, symtab_t *symtab,
|
|||
sym->table = nullptr;
|
||||
}
|
||||
|
||||
if (!spec.type_expr && !spec.is_function) {
|
||||
spec = default_type (spec, sym);
|
||||
}
|
||||
spec = spec_process (spec, ctx);
|
||||
if (!spec.storage) {
|
||||
spec.storage = current_storage;
|
||||
}
|
||||
|
||||
if (spec.type && (spec.is_typedef || !sym->type || !is_func (sym->type))) {
|
||||
sym->type = append_type (spec.sym->type, spec.type);
|
||||
}
|
||||
sym->type = spec.type;
|
||||
|
||||
if (spec.is_typedef) {
|
||||
if (init) {
|
||||
|
@ -311,7 +307,7 @@ declare_symbol (specifier_t spec, const expr_t *init, symtab_t *symtab,
|
|||
sym->type = find_type (alias_type (sym->type, sym->type, sym->name));
|
||||
symtab_addsymbol (symtab, sym);
|
||||
} else {
|
||||
if (spec.is_function && is_func (sym->type)) {
|
||||
if (is_func (sym->type)) {
|
||||
if (init) {
|
||||
error (0, "function %s is initialized", sym->name);
|
||||
}
|
||||
|
@ -328,10 +324,10 @@ declare_symbol (specifier_t spec, const expr_t *init, symtab_t *symtab,
|
|||
}
|
||||
|
||||
symbol_t *
|
||||
declare_field (specifier_t spec, symtab_t *symtab)
|
||||
declare_field (specifier_t spec, symtab_t *symtab, rua_ctx_t *ctx)
|
||||
{
|
||||
symbol_t *s = spec.sym;
|
||||
spec = default_type (spec, s);
|
||||
spec = spec_process (spec, ctx);
|
||||
s->type = find_type (append_type (s->type, spec.type));
|
||||
s->sy_type = sy_offset;
|
||||
s->visibility = current_visibility;
|
||||
|
|
|
@ -202,6 +202,14 @@ type_t type_param = {
|
|||
.type = ev_invalid,
|
||||
.meta = ty_struct,
|
||||
};
|
||||
static type_t type_param_pointer = {
|
||||
.type = ev_ptr,
|
||||
.alignment = 1,
|
||||
.width = 1,
|
||||
.columns = 1,
|
||||
.meta = ty_basic,
|
||||
.fldptr.type = &type_param,
|
||||
};
|
||||
type_t type_zero = {
|
||||
.type = ev_invalid,
|
||||
.meta = ty_struct,
|
||||
|
@ -222,7 +230,7 @@ type_t type_xdef_pointer = {
|
|||
.width = 1,
|
||||
.columns = 1,
|
||||
.meta = ty_basic,
|
||||
{{&type_xdef}},
|
||||
.fldptr.type = &type_xdef,
|
||||
};
|
||||
type_t type_xdefs = {
|
||||
.type = ev_invalid,
|
||||
|
@ -1668,6 +1676,10 @@ type_assignable (const type_t *dst, const type_t *src)
|
|||
// any field = any field
|
||||
if (dst->type == ev_field && src->type == ev_field)
|
||||
return true;
|
||||
if (is_pointer (dst) && is_func (src)) {
|
||||
auto type = dereference_type (dst);
|
||||
return type == src;
|
||||
}
|
||||
// pointer = array
|
||||
if (is_pointer (dst) && is_array (src)) {
|
||||
if (is_void (dst->fldptr.type)
|
||||
|
@ -2063,6 +2075,7 @@ static void
|
|||
chain_structural_types (void)
|
||||
{
|
||||
chain_type (&type_param);
|
||||
chain_type (&type_param_pointer);
|
||||
chain_type (&type_zero);
|
||||
chain_type (&type_type_encodings);
|
||||
chain_type (&type_xdef);
|
||||
|
@ -2203,6 +2216,7 @@ init_types (void)
|
|||
|
||||
make_structure ("@zero", 'u', zero_struct, &type_zero);
|
||||
make_structure ("@param", 'u', param_struct, &type_param);
|
||||
|
||||
build_vector_struct (&type_vector, false);
|
||||
|
||||
make_structure ("@type_encodings", 's', type_encoding_struct,
|
||||
|
@ -2210,7 +2224,7 @@ init_types (void)
|
|||
make_structure ("@xdef", 's', xdef_struct, &type_xdef);
|
||||
make_structure ("@xdefs", 's', xdefs_struct, &type_xdefs);
|
||||
|
||||
va_list_struct[1].type = pointer_type (&type_param);
|
||||
va_list_struct[1].type = &type_param_pointer;
|
||||
make_structure ("@va_list", 's', va_list_struct, &type_va_list);
|
||||
|
||||
build_vector_struct (&type_quaternion, false);
|
||||
|
|
Loading…
Reference in a new issue