From 157549e119b46989da7c807246dd362ee12ba003 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 30 Nov 2014 18:56:37 -0800 Subject: [PATCH] Fix a bug where aliased constructors of nullable methodmaps could not be used. --- sourcepawn/compiler/sc.h | 3 ++- sourcepawn/compiler/sc2.cpp | 7 +++++-- sourcepawn/compiler/sc3.cpp | 14 ++++++++++++-- .../compiler/tests/ok-use-aliased-constructor.sp | 12 ++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 sourcepawn/compiler/tests/ok-use-aliased-constructor.sp diff --git a/sourcepawn/compiler/sc.h b/sourcepawn/compiler/sc.h index e98e7cfc..07f3d444 100644 --- a/sourcepawn/compiler/sc.h +++ b/sourcepawn/compiler/sc.h @@ -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); diff --git a/sourcepawn/compiler/sc2.cpp b/sourcepawn/compiler/sc2.cpp index f4d83b9d..353b0b86 100644 --- a/sourcepawn/compiler/sc2.cpp +++ b/sourcepawn/compiler/sc2.cpp @@ -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; } diff --git a/sourcepawn/compiler/sc3.cpp b/sourcepawn/compiler/sc3.cpp index 240739ec..6f3c7977 100644 --- a/sourcepawn/compiler/sc3.cpp +++ b/sourcepawn/compiler/sc3.cpp @@ -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; diff --git a/sourcepawn/compiler/tests/ok-use-aliased-constructor.sp b/sourcepawn/compiler/tests/ok-use-aliased-constructor.sp new file mode 100644 index 00000000..1dca0339 --- /dev/null +++ b/sourcepawn/compiler/tests/ok-use-aliased-constructor.sp @@ -0,0 +1,12 @@ +native Handle:CreateHandle(); + +methodmap Handle __nullable__ +{ + public native Handle() = CreateHandle; + public native ~Handle(); +}; + +public main() +{ + CreateHandle(); +}