diff --git a/source/compiler/sc.h b/source/compiler/sc.h index ea53507..38eca26 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -516,13 +516,18 @@ enum { /* identifier types */ estAUTOMATON, estSTATE }; -enum { /* symbol types */ - essNONLABEL, /* find symbols of any type but labels */ - essVARCONST, /* array, single variable or named constant */ - essARRAY, - essCONST, - essFUNCTN, - essLABEL +enum { /* symbol type flags */ + esfLABEL = 1 << 0, + esfCONST = 1 << 1, /* named constant */ + esfVARIABLE = 1 << 2, /* single variable */ + esfARRAY = 1 << 3, /* array */ + esfFUNCTION = 1 << 4, /* Pawn or native function */ + + /* find symbols of any type but labels */ + esfNONLABEL = esfCONST | esfVARIABLE | esfARRAY | esfFUNCTION, + + /* find an array, a single variable, or a named constant */ + esfVARCONST = esfCONST | esfVARIABLE | esfARRAY }; /* interface functions */ diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 4ec4351..241b605 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -2028,7 +2028,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst } else { tag=pc_addtag(NULL); if (lex(&val,&str)!=tSYMBOL) /* read in (new) token */ - error_suggest(20,str,NULL,estSYMBOL,essFUNCTN); /* invalid symbol name */ + error_suggest(20,str,NULL,estSYMBOL,esfFUNCTION); /* invalid symbol name */ assert(strlen(str)<=sNAMEMAX); strcpy(name,str); /* save symbol name */ } /* if */ @@ -4879,7 +4879,7 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst) case iLABEL: if (testlabs) { if ((sym->usage & uDEFINE)==0) { - error_suggest(19,sym->name,NULL,estSYMBOL,essLABEL); /* not a label: ... */ + error_suggest(19,sym->name,NULL,estSYMBOL,esfLABEL); /* not a label: ... */ } else if ((sym->usage & uREAD)==0) { errorset(sSETPOS,sym->lnumber); error(203,sym->name); /* symbol isn't used: ... */ @@ -5983,7 +5983,7 @@ static void dogoto(void) // sym->compound (nesting level of the label) against nestlevel; // if sym->compound < nestlevel, call the destructor operator } else { - error_suggest(20,st,NULL,estSYMBOL,essLABEL); /* illegal symbol name */ + error_suggest(20,st,NULL,estSYMBOL,esfLABEL); /* illegal symbol name */ } /* if */ needtoken(tTERM); } @@ -6023,7 +6023,7 @@ static symbol *fetchlab(char *name) sym=findloc(name); /* labels are local in scope */ if (sym) { if (sym->ident!=iLABEL) - error_suggest(19,sym->name,NULL,estSYMBOL,essLABEL); /* not a label: ... */ + error_suggest(19,sym->name,NULL,estSYMBOL,esfLABEL); /* not a label: ... */ } else { sym=addsym(name,getlabel(),iLABEL,sLOCAL,0,0); assert(sym!=NULL); /* fatal error 103 must be given on error */ diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index f0bc8e6..ff6147f 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -1349,13 +1349,13 @@ static int hier2(value *lval) if (sym==NULL) sym=findglb(st,sSTATEVAR); if (sym==NULL) - return error_suggest(17,st,NULL,estSYMBOL,essVARCONST); /* undefined symbol */ + return error_suggest(17,st,NULL,estSYMBOL,esfVARCONST); /* undefined symbol */ if (sym->ident==iCONSTEXPR) error(39); /* constant symbol has no size */ else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) error(72); /* "function" symbol has no size */ else if ((sym->usage & uDEFINE)==0) - return error_suggest(17,st,NULL,estSYMBOL,essVARCONST); /* undefined symbol (symbol is in the table, but it is "used" only) */ + return error_suggest(17,st,NULL,estSYMBOL,esfVARCONST); /* undefined symbol (symbol is in the table, but it is "used" only) */ clear_value(lval); lval->ident=iCONSTEXPR; lval->constval=1; /* preset */ @@ -1370,7 +1370,7 @@ static int hier2(value *lval) int cmptag=subsym->x.tags.index; tokeninfo(&val,&idxname); if ((idxsym=findconst(idxname,&cmptag))==NULL) - error_suggest(80,idxname,NULL,estSYMBOL,essCONST); /* unknown symbol, or non-constant */ + error_suggest(80,idxname,NULL,estSYMBOL,esfCONST); /* unknown symbol, or non-constant */ else if (cmptag>1) error(91,idxname); /* ambiguous constant */ } /* if */ @@ -1406,9 +1406,9 @@ static int hier2(value *lval) if (sym==NULL) sym=findglb(st,sSTATEVAR); if (sym==NULL) - return error_suggest(17,st,NULL,estSYMBOL,essNONLABEL); /* undefined symbol */ + return error_suggest(17,st,NULL,estSYMBOL,esfNONLABEL); /* undefined symbol */ if ((sym->usage & uDEFINE)==0) - return error_suggest(17,st,NULL,estSYMBOL,essNONLABEL); /* undefined symbol (symbol is in the table, but it is "used" only) */ + return error_suggest(17,st,NULL,estSYMBOL,esfNONLABEL); /* undefined symbol (symbol is in the table, but it is "used" only) */ tag=sym->tag; } /* if */ if (sym!=NULL && (sym->ident==iARRAY || sym->ident==iREFARRAY)) { @@ -1422,7 +1422,7 @@ static int hier2(value *lval) int cmptag=subsym->x.tags.index; tokeninfo(&val,&idxname); if ((idxsym=findconst(idxname,&cmptag))==NULL) - error_suggest(80,idxname,NULL,estSYMBOL,essCONST); /* unknown symbol, or non-constant */ + error_suggest(80,idxname,NULL,estSYMBOL,esfCONST); /* unknown symbol, or non-constant */ else if (cmptag>1) error(91,idxname); /* ambiguous constant */ } /* if */ @@ -1598,7 +1598,7 @@ restart: needtoken(close); return FALSE; } else if (sym->ident!=iARRAY && sym->ident!=iREFARRAY){ - error_suggest(28,sym->name,NULL,estSYMBOL,essARRAY);/* cannot subscript, variable is not an array */ + error_suggest(28,sym->name,NULL,estSYMBOL,esfARRAY);/* cannot subscript, variable is not an array */ needtoken(close); return FALSE; } else if (sym->dim.array.level>0 && close!=']') { @@ -1851,10 +1851,10 @@ static int primary(value *lval) * implemented, issue an error */ if ((sym->usage & uPROTOTYPED)==0) - error_suggest(17,st,NULL,estSYMBOL,essFUNCTN); /* undefined symbol */ + error_suggest(17,st,NULL,estSYMBOL,esfFUNCTION); /* undefined symbol */ } else { if ((sym->usage & uDEFINE)==0) - error_suggest(17,st,NULL,estSYMBOL,essVARCONST); /* undefined symbol */ + error_suggest(17,st,NULL,estSYMBOL,esfVARCONST); /* undefined symbol */ lval->sym=sym; lval->ident=sym->ident; lval->tag=sym->tag; @@ -1867,7 +1867,7 @@ static int primary(value *lval) } /* if */ } else { if (!sc_allowproccall) - return error_suggest(17,st,NULL,estSYMBOL,essVARCONST); /* undefined symbol */ + return error_suggest(17,st,NULL,estSYMBOL,esfVARCONST); /* undefined symbol */ /* an unknown symbol, but used in a way compatible with the "procedure * call" syntax. So assume that the symbol refers to a function. */ diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index 4ba4555..7429c3f 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -259,31 +259,31 @@ static short lastfile; } /* if */ if (number<100) { - assert(number>0 && number<(1+arraysize(errmsg))); + assert(number>0 && number<(1+sizeof(errmsg)/sizeof(errmsg[0]))); msg=errmsg[number-1]; pre=prefix[0]; errflag=TRUE; /* set errflag (skip rest of erroneous expression) */ errnum++; } else if (number<200) { - assert(number>=100 && number<(100+arraysize(fatalmsg))); + assert(number>=100 && number<(100+sizeof(fatalmsg)/sizeof(fatalmsg[0]))); msg=fatalmsg[number-100]; pre=prefix[1]; errnum++; /* a fatal error also counts as an error */ } else if (errwarn) { - assert(number>=200 && number<(200+arraysize(warnmsg))); + assert(number>=200 && number<(200+sizeof(warnmsg)/sizeof(warnmsg[0]))); msg=warnmsg[number-200]; pre=prefix[0]; errflag=TRUE; errnum++; } else { - assert(number>=200 && number<(200+arraysize(warnmsg))); + assert(number>=200 && number<(200+sizeof(warnmsg)/sizeof(warnmsg[0]))); msg=warnmsg[number-200]; pre=prefix[2]; warnnum++; } /* if */ if (notice!=0) { - assert(notice>0 && notice<(1+arraysize(noticemsg)) && noticemsg[notice-1][0]!='\0'); + assert(notice>0 && notice<(1+sizeof(noticemsg)/sizeof(noticemsg[0])) && noticemsg[notice-1][0]!='\0'); strcpy(string,msg); strcpy(&string[strlen(string)-1],noticemsg[notice-1]); msg=string; @@ -502,7 +502,6 @@ static int find_closest_symbol_table(const char *name,const symbol *root,int sym int dist,max_dist,closest_dist=INT_MAX; char symname[2*sNAMEMAX+16]; symbol *sym; - int ident; assert(closest_sym!=NULL); *closest_sym =NULL; assert(name!=NULL); @@ -510,33 +509,41 @@ static int find_closest_symbol_table(const char *name,const symbol *root,int sym for (sym=root->next; sym!=NULL; sym=sym->next) { if (sym->fnumber!=-1 && sym->fnumber!=fcurrent) continue; - if ((sym->usage & uDEFINE)==0) + if ((sym->usage & uDEFINE)==0 && (sym->ident!=iFUNCTN || (sym->usage & (uNATIVE | uPROTOTYPED))!=uPROTOTYPED)) continue; - ident=sym->ident; - if (symboltype==essNONLABEL) { - if (ident==iLABEL) + switch (sym->ident) + { + case iLABEL: + if ((symboltype & esfLABEL)==0) continue; - } else if (symboltype==essVARCONST) { - if (ident!=iCONSTEXPR && ident!=iVARIABLE && ident!=iREFERENCE && ident!=iARRAY && ident!=iREFARRAY) + break; + case iCONSTEXPR: + if ((symboltype & esfCONST)==0) continue; - } else if (symboltype==essARRAY) { - if (ident!=iARRAY && ident!=iREFARRAY) + break; + case iVARIABLE: + case iREFERENCE: + if ((symboltype & esfVARIABLE)==0) continue; - } else if (symboltype==essCONST) { - if (ident!=iCONSTEXPR) + break; + case iARRAY: + case iREFARRAY: + if ((symboltype & esfARRAY)==0) continue; - } else if (symboltype==essFUNCTN) { - if (ident!=iFUNCTN && ident!=iREFFUNC) + break; + case iFUNCTN: + case iREFFUNC: + if ((symboltype & esfFUNCTION)==0) continue; - } else if (symboltype==essLABEL) { - if (ident!=iLABEL) - continue; - } /* if */ + break; + default: + assert(0); + } /* switch */ funcdisplayname(symname,sym->name); dist=levenshtein_distance(name,symname); if (dist>max_dist || dist>=closest_dist) continue; - *closest_sym =sym; + *closest_sym=sym; closest_dist=dist; if (closest_dist<=1) break; @@ -642,6 +649,7 @@ SC_FUNC int error_suggest(int number,const char *name,const char *name2,int type { char string[sNAMEMAX*2+2]; /* for ":" */ const char *closest_name=NULL; + symbol *closest_sym; /* don't bother finding the closest names on errors * that aren't going to be shown on the 1'st pass @@ -649,28 +657,30 @@ SC_FUNC int error_suggest(int number,const char *name,const char *name2,int type if ((errflag || sc_status!=statWRITE) && (number<100 || number>=200)) return 0; - if (type==estSYMBOL || (type==estNONSYMBOL && tMIDDLEname; + } else if (type==estNONSYMBOL) { + if (tMIDDLEname; } else if (type==estAUTOMATON) { constvalue *closest_automaton=find_closest_automaton(name); if (closest_automaton!=NULL) closest_name=closest_automaton->name; } else if (type==estSTATE) { constvalue *closest_state=find_closest_state(name,subtype); - if (closest_state !=NULL) { + if (closest_state!=NULL) { closest_name=closest_state->name; } else { constvalue *closest_automaton=find_closest_automaton_for_state(name,subtype); - if (closest_automaton !=NULL) { - sprintf(string,"%s:%s", closest_automaton->name,name); + if (closest_automaton!=NULL) { + sprintf(string,"%s:%s",closest_automaton->name,name); closest_name=string; } /* if */ } /* if */ diff --git a/source/compiler/tests/gh_353_symbol_suggestions.meta b/source/compiler/tests/gh_353_symbol_suggestions.meta index d1504cc..f9d8f94 100644 --- a/source/compiler/tests/gh_353_symbol_suggestions.meta +++ b/source/compiler/tests/gh_353_symbol_suggestions.meta @@ -8,18 +8,21 @@ gh_353_symbol_suggestions.pwn(40) : error 017: undefined symbol "ab" gh_353_symbol_suggestions.pwn(41) : error 017: undefined symbol "ab" gh_353_symbol_suggestions.pwn(50) : error 017: undefined symbol "staticval" gh_353_symbol_suggestions.pwn(58) : error 017: undefined symbol "test_nosuggest6_val" -gh_353_symbol_suggestions.pwn(67) : error 017: undefined symbol "val"; did you mean "var"? -gh_353_symbol_suggestions.pwn(71) : error 017: undefined symbol "celmax"; did you mean "cellmax"? -gh_353_symbol_suggestions.pwn(75) : error 017: undefined symbol "strcaf"; did you mean "strcat"? -gh_353_symbol_suggestions.pwn(78) : error 017: undefined symbol "test_e17"; did you mean "test_e017"? -gh_353_symbol_suggestions.pwn(87) : error 019: not a label: "lb"; did you mean "lbl"? -gh_353_symbol_suggestions.pwn(94) : error 020: invalid symbol name "assert"; did you mean "asset"? -gh_353_symbol_suggestions.pwn(105) : error 080: unknown symbol, or not a constant symbol (symbol "idx"); did you mean "id"? -gh_353_symbol_suggestions.pwn(116) : error 086: unknown automaton "automaton1"; did you mean "automaton_1"? -gh_353_symbol_suggestions.pwn(116) : error 036: empty statement -gh_353_symbol_suggestions.pwn(123) : error 087: unknown state "BEING1" for automaton "automaton_2"; did you mean "BEING_1"? -gh_353_symbol_suggestions.pwn(123) : error 036: empty statement -gh_353_symbol_suggestions.pwn(126) : error 087: unknown state "STATE_1" for automaton "automaton_2"; did you mean "automaton_1:STATE_1"? -gh_353_symbol_suggestions.pwn(126) : error 036: empty statement +gh_353_symbol_suggestions.pwn(67) : error 020: invalid symbol name "" +gh_353_symbol_suggestions.pwn(68) : error 020: invalid symbol name "" +gh_353_symbol_suggestions.pwn(77) : error 017: undefined symbol "val"; did you mean "var"? +gh_353_symbol_suggestions.pwn(81) : error 017: undefined symbol "celmax"; did you mean "cellmax"? +gh_353_symbol_suggestions.pwn(85) : error 017: undefined symbol "strcaf"; did you mean "strcat"? +gh_353_symbol_suggestions.pwn(88) : error 017: undefined symbol "DoNothin"; did you mean "DoNothing"? +gh_353_symbol_suggestions.pwn(91) : error 017: undefined symbol "test_e17"; did you mean "test_e017"? +gh_353_symbol_suggestions.pwn(102) : error 019: not a label: "lb"; did you mean "lbl"? +gh_353_symbol_suggestions.pwn(109) : error 020: invalid symbol name "assert"; did you mean "asset"? +gh_353_symbol_suggestions.pwn(120) : error 080: unknown symbol, or not a constant symbol (symbol "idx"); did you mean "id"? +gh_353_symbol_suggestions.pwn(131) : error 086: unknown automaton "automaton1"; did you mean "automaton_1"? +gh_353_symbol_suggestions.pwn(131) : error 036: empty statement +gh_353_symbol_suggestions.pwn(138) : error 087: unknown state "BEING1" for automaton "automaton_2"; did you mean "BEING_1"? +gh_353_symbol_suggestions.pwn(138) : error 036: empty statement +gh_353_symbol_suggestions.pwn(141) : error 087: unknown state "STATE_1" for automaton "automaton_2"; did you mean "automaton_1:STATE_1"? +gh_353_symbol_suggestions.pwn(141) : error 036: empty statement """ } diff --git a/source/compiler/tests/gh_353_symbol_suggestions.pwn b/source/compiler/tests/gh_353_symbol_suggestions.pwn index becde05..81a22d6 100644 --- a/source/compiler/tests/gh_353_symbol_suggestions.pwn +++ b/source/compiler/tests/gh_353_symbol_suggestions.pwn @@ -59,6 +59,16 @@ public test_nosuggest6() } static test_nosuggest6_val; +forward test_nosuggest7(); +public test_nosuggest7() +{ + // The compiler shouldn't try to suggest anything when tagof is used on + // string/numeric literals. + new a = tagof 0; + new b = tagof ""; + return a + b; +} + forward test_e017(); public test_e017() { @@ -74,9 +84,14 @@ public test_e017() new str[4] = "a"; strcaf(str, "b"); + // error 017: undefined symbol "DoNothin"; did you mean "DoNothing"? + DoNothin(); + // error 017: undefined symbol "test_e17"; did you mean "test_e017"? printf("%d\n", tagof test_e17); } +DoNothing(){} +#pragma unused DoNothing forward test_e019(); public test_e019()