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(); +}