mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-25 03:31:25 +00:00
[qfcc] Rework method ivar access
While expression symbols worked for what they are, they weren't so good for ivar access because every ivar of a class (and its super classes) would be accessed at method scope creation, generating spurious access errors if any were private. That is, when the access checks worked at all.
This commit is contained in:
parent
5200c3f518
commit
66b8ab6890
6 changed files with 39 additions and 5 deletions
|
@ -56,8 +56,14 @@ typedef enum {
|
|||
sy_expr, ///< symbol refers to an expression
|
||||
sy_func, ///< symbol refers to a function
|
||||
sy_class, ///< symbol refers to a class
|
||||
sy_convert, ///< symbol refers to a conversion function
|
||||
} sy_type_e;
|
||||
|
||||
typedef struct symconv_s {
|
||||
struct expr_s *(*conv) (struct symbol_s *symbol, void *data);
|
||||
void *data;
|
||||
} symconv_t;
|
||||
|
||||
typedef struct symbol_s {
|
||||
struct symbol_s *next; ///< chain of symbols in symbol table
|
||||
struct symtab_s *table; ///< symbol table that owns this symbol
|
||||
|
@ -72,6 +78,7 @@ typedef struct symbol_s {
|
|||
struct ex_value_s *value; ///< sy_const
|
||||
struct expr_s *expr; ///< sy_expr
|
||||
struct function_s *func; ///< sy_func
|
||||
symconv_t convert; ///< sy_convert
|
||||
} s;
|
||||
} symbol_t;
|
||||
|
||||
|
@ -92,6 +99,7 @@ typedef struct symtab_s {
|
|||
symbol_t *symbols; ///< chain of symbols in this table
|
||||
symbol_t **symtail; ///< keep chain in declaration order
|
||||
struct defspace_s *space; ///< storage for vars in scope symtabs
|
||||
struct class_s *class; ///< owning class if ivar scope
|
||||
} symtab_t;
|
||||
|
||||
const char *symtype_str (sy_type_e type) __attribute__((const));
|
||||
|
|
|
@ -1050,8 +1050,11 @@ class_find_ivar (class_t *class, int vis, const char *name)
|
|||
}
|
||||
ivar = symtab_lookup (class->ivars, name);
|
||||
if (ivar) {
|
||||
if (ivar->visibility > (vis_t) vis)
|
||||
if (ivar->visibility > (vis_t) vis
|
||||
|| (ivar->table->class != class
|
||||
&& ivar->visibility > vis_protected)) {
|
||||
goto access_error;
|
||||
}
|
||||
return ivar;
|
||||
}
|
||||
error (0, "%s.%s does not exist", class->name, name);
|
||||
|
@ -1180,6 +1183,7 @@ class_new_ivars (class_t *class)
|
|||
if (class->super_class)
|
||||
super_ivars = class->super_class->ivars;
|
||||
ivars = new_symtab (super_ivars, stab_local);
|
||||
ivars->class = class;
|
||||
return ivars;
|
||||
}
|
||||
|
||||
|
@ -1756,6 +1760,15 @@ class_ivar_scope (class_type_t *class_type, symtab_t *parent)
|
|||
return symtab_flat_copy (class->ivars, parent);
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
class_dereference_ivar (symbol_t *sym, void *_self)
|
||||
{
|
||||
expr_t *self = (expr_t *) _self;
|
||||
|
||||
return field_expr (copy_expr (self),
|
||||
new_symbol_expr (new_symbol (sym->name)));
|
||||
}
|
||||
|
||||
void
|
||||
class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope,
|
||||
symtab_t *param_scope)
|
||||
|
@ -1769,8 +1782,9 @@ class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope,
|
|||
if (!ivar_scope)
|
||||
return;
|
||||
self = symtab_lookup (param_scope, "self");
|
||||
if (!self)
|
||||
if (!self) {
|
||||
internal_error (0, "I've lost my self!");
|
||||
}
|
||||
self_expr = new_symbol_expr (self);
|
||||
if (self->type != class_ptr) {
|
||||
debug (0, "class method scope");
|
||||
|
@ -1780,9 +1794,9 @@ class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope,
|
|||
for (sym = ivar_scope->symbols; sym; sym = sym->next) {
|
||||
if (sym->sy_type != sy_var)
|
||||
continue;
|
||||
sym->sy_type = sy_expr;
|
||||
sym->s.expr = field_expr (copy_expr (self_expr),
|
||||
new_symbol_expr (new_symbol (sym->name)));
|
||||
sym->sy_type = sy_convert;
|
||||
sym->s.convert.conv = class_dereference_ivar;
|
||||
sym->s.convert.data = self_expr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,10 @@ convert_name (expr_t *e)
|
|||
//FIXME need a def
|
||||
return;
|
||||
}
|
||||
if (sym->sy_type == sy_convert) {
|
||||
new = sym->s.convert.conv (sym, sym->s.convert.data);
|
||||
goto convert;
|
||||
}
|
||||
if (sym->sy_type == sy_expr) {
|
||||
new = copy_expr (sym->s.expr);
|
||||
goto convert;
|
||||
|
|
|
@ -101,6 +101,8 @@ check_valid_lvalue (expr_t *expr)
|
|||
break;
|
||||
case sy_class:
|
||||
break;
|
||||
case sy_convert:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ex_temp:
|
||||
|
|
|
@ -151,6 +151,9 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type)
|
|||
}
|
||||
anonymous = s->type->t.symtab;
|
||||
for (as = anonymous->symbols; as; as = as->next) {
|
||||
if (as->visibility == vis_anonymous || as->sy_type!= sy_var) {
|
||||
continue;
|
||||
}
|
||||
if (Hash_Find (symtab->tab, as->name)) {
|
||||
error (0, "ambiguous field `%s' in anonymous %s",
|
||||
as->name, su == 's' ? "struct" : "union");
|
||||
|
@ -158,6 +161,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type)
|
|||
s->next = copy_symbol (as);
|
||||
s = s->next;
|
||||
s->s.offset += offset;
|
||||
s->table = symtab;
|
||||
Hash_Add (symtab->tab, s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ static const char *sy_type_names[] = {
|
|||
"sy_expr",
|
||||
"sy_func",
|
||||
"sy_class",
|
||||
"sy_convert",
|
||||
};
|
||||
|
||||
const char *
|
||||
|
@ -165,6 +166,7 @@ symbol_t *
|
|||
copy_symbol (symbol_t *symbol)
|
||||
{
|
||||
symbol_t *sym = new_symbol (symbol->name);
|
||||
sym->visibility = symbol->visibility;
|
||||
sym->type = symbol->type;
|
||||
sym->params = copy_params (symbol->params);
|
||||
sym->sy_type = symbol->sy_type;
|
||||
|
|
Loading…
Reference in a new issue