[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:
Bill Currie 2020-03-05 18:45:47 +09:00
parent 5200c3f518
commit 66b8ab6890
6 changed files with 39 additions and 5 deletions

View file

@ -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));

View file

@ -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;
}
}

View file

@ -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;

View file

@ -101,6 +101,8 @@ check_valid_lvalue (expr_t *expr)
break;
case sy_class:
break;
case sy_convert:
break;
}
break;
case ex_temp:

View file

@ -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);
}
}

View file

@ -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;