Fix a bug where aliased constructors of nullable methodmaps could not be used.

This commit is contained in:
David Anderson 2014-11-30 18:56:37 -08:00
parent 9f5c8b60ae
commit 157549e119
4 changed files with 31 additions and 5 deletions

View File

@ -246,6 +246,7 @@ struct methodmap_method_s;
typedef struct value_s {
symbol *sym; /* symbol in symbol table, NULL for (constant) expression */
symbol *proxy; /* original symbol if resolved via a proxy */
cell constval; /* value of the constant expression (if ident==iCONSTEXPR)
* also used for the size of a literal array */
int tag; /* tag (of the expression) */
@ -640,7 +641,7 @@ void delete_symbol(symbol *root,symbol *sym);
void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
int refer_symbol(symbol *entry,symbol *bywhom);
void markusage(symbol *sym,int usage);
symbol *findglb(const char *name,int filter);
symbol *findglb(const char *name,int filter,symbol **alias = NULL);
symbol *findloc(const char *name);
symbol *findconst(const char *name,int *matchtag);
symbol *finddepend(const symbol *parent);

View File

@ -2999,7 +2999,7 @@ void markusage(symbol *sym,int usage)
*
* Returns a pointer to the global symbol (if found) or NULL (if not found)
*/
symbol *findglb(const char *name,int filter)
symbol *findglb(const char *name, int filter, symbol **alias)
{
/* find a symbol with a matching automaton first */
symbol *sym=NULL;
@ -3024,8 +3024,11 @@ symbol *findglb(const char *name,int filter)
if (sym==NULL)
sym=FindInHashTable(sp_Globals,name,fcurrent);
if (sym && sym->ident == iPROXY)
if (sym && sym->ident == iPROXY) {
if (alias)
*alias = sym;
return sym->target;
}
return sym;
}

View File

@ -2265,7 +2265,12 @@ restart:
error(4,symname); /* function not defined */
} /* if */
if (sym->flags & flgPROXIED) {
// Check whether we're calling a constructor. This is a bit hacky, since
// we're relying on whatever the lval state is.
if ((sym->flags & flgPROXIED) &&
lval1->proxy &&
lval1->proxy->target == sym)
{
// Only constructors should be proxied, but we check anyway.
assert(!implicitthis);
if (methodmap_t *methodmap = methodmap_find_by_tag(sym->tag)) {
@ -2310,6 +2315,7 @@ restart:
funcenum_t *fe = funcenum_for_symbol(target);
lval1->sym = NULL;
lval1->proxy = NULL;
lval1->ident = iCONSTEXPR;
lval1->constval = (public_index << 1) | 1;
lval1->tag = fe->tag;
@ -2396,7 +2402,8 @@ static int primary(value *lval)
} /* if */
} /* if */
/* now try a global variable */
if ((sym=findglb(st,sSTATEVAR))!=0) {
symbol *alias = NULL;
if ((sym = findglb(st, sSTATEVAR, &alias)) != 0) {
if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) {
/* if the function is only in the table because it was inserted as a
* stub in the first pass (i.e. it was "used" but never declared or
@ -2408,6 +2415,7 @@ static int primary(value *lval)
if ((sym->usage & uDEFINE)==0)
error(17,st);
lval->sym=sym;
lval->proxy=alias;
lval->ident=sym->ident;
lval->tag=sym->tag;
if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
@ -2431,6 +2439,7 @@ static int primary(value *lval)
assert(sym!=NULL);
assert(sym->ident==iFUNCTN || sym->ident==iREFFUNC);
lval->sym=sym;
lval->proxy=alias;
lval->ident=sym->ident;
lval->tag=sym->tag;
return FALSE; /* return 0 for function (not an lvalue) */
@ -2446,6 +2455,7 @@ static int primary(value *lval)
static void clear_value(value *lval)
{
lval->sym=NULL;
lval->proxy=NULL;
lval->constval=0L;
lval->tag=0;
lval->ident=0;

View File

@ -0,0 +1,12 @@
native Handle:CreateHandle();
methodmap Handle __nullable__
{
public native Handle() = CreateHandle;
public native ~Handle();
};
public main()
{
CreateHandle();
}