Skip to content

Commit 6592db0

Browse files
committed
Force a reparse when encountering a late forward
This hopefully fixes a bug where code for a custom assignment operator wasn't being generated because the compiler thought that it's not used but it still generated a call (which resulting in infinite recursion). It happened only if some function returned a tagged result and wasn't forwarded before its first use. Interestingly the compiler didn't issue a reparse when it encountered the forward declaration and no warning was printed. Perhaps the authors forgot to do this when they were adding the forward syntax (it certainly was added after what is now called "old-style prototypes"). See 8) here: http://forum.sa-mp.com/showthread.php?t=355877 --------- test code -------- #include <a_samp> _:operator=(Taggg:a) { return _:a + 5; } main() { new a = d(); printf("%d", a); } forward Taggg:d(); Taggg:d() { return Taggg:5; } ----- end of test code -----
1 parent 1d1244c commit 6592db0

File tree

1 file changed

+19
-13
lines changed

1 file changed

+19
-13
lines changed

source/compiler/sc1.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3257,6 +3257,23 @@ SC_FUNC char *funcdisplayname(char *dest,char *funcname)
32573257
return dest;
32583258
}
32593259

3260+
static void check_reparse(symbol *sym)
3261+
{
3262+
/* if the function was used before being declared, and it has a tag for the
3263+
* result, add a third pass (as second "skimming" parse) because the function
3264+
* result may have been used with user-defined operators, which have now
3265+
* been incorrectly flagged (as the return tag was unknown at the time of
3266+
* the call)
3267+
*/
3268+
if ((sym->usage & (uPROTOTYPED | uREAD))==uREAD && sym->tag!=0) {
3269+
int curstatus=sc_status;
3270+
sc_status=statWRITE; /* temporarily set status to WRITE, so the warning isn't blocked */
3271+
error(208);
3272+
sc_status=curstatus;
3273+
sc_reparse=TRUE; /* must add another pass to "initial scan" phase */
3274+
} /* if */
3275+
}
3276+
32603277
static void funcstub(int fnative)
32613278
{
32623279
int tok,tag,fpublic;
@@ -3328,6 +3345,7 @@ static void funcstub(int fnative)
33283345
sym->usage|=uPUBLIC;
33293346
} /* if */
33303347
sym->usage|=uFORWARD;
3348+
check_reparse(sym);
33313349

33323350
declargs(sym,FALSE);
33333351
/* "declargs()" found the ")" */
@@ -3454,19 +3472,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc
34543472
sym->usage|=uPUBLIC;
34553473
if (fstatic)
34563474
sym->fnumber=filenum;
3457-
/* if the function was used before being declared, and it has a tag for the
3458-
* result, add a third pass (as second "skimming" parse) because the function
3459-
* result may have been used with user-defined operators, which have now
3460-
* been incorrectly flagged (as the return tag was unknown at the time of
3461-
* the call)
3462-
*/
3463-
if ((sym->usage & (uPROTOTYPED | uREAD))==uREAD && sym->tag!=0) {
3464-
int curstatus=sc_status;
3465-
sc_status=statWRITE; /* temporarily set status to WRITE, so the warning isn't blocked */
3466-
error(208);
3467-
sc_status=curstatus;
3468-
sc_reparse=TRUE; /* must add another pass to "initial scan" phase */
3469-
} /* if */
3475+
check_reparse(sym);
34703476
/* we want public functions to be explicitly prototyped, as they are called
34713477
* from the outside
34723478
*/

0 commit comments

Comments
 (0)