Skip to content

[MERGED] warning 24X: enum item "%s" not handled in switch #549

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions source/compiler/sc.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ typedef struct s_symbol {
struct {
int index; /* array & enum: tag of array indices or the enum item */
int field; /* enumeration fields, where a size is attached to the field */
int unique; /* number of enumeration elements with unique value */
} tags; /* extra tags */
constvalue *lib; /* native function: library it is part of */
long stacksize; /* normal/public function: stack requirements */
Expand Down
54 changes: 52 additions & 2 deletions source/compiler/sc1.c
Original file line number Diff line number Diff line change
Expand Up @@ -2928,6 +2928,7 @@ static void decl_enum(int vclass,int fstatic)
cell val,value,size;
char *str;
int tag,explicittag;
int unique;
cell increment,multiplier;
constvalue_root *enumroot=NULL;
symbol *enumsym=NULL;
Expand Down Expand Up @@ -2979,9 +2980,10 @@ static void decl_enum(int vclass,int fstatic)
enumsym=add_constant(enumname,0,vclass,tag);
if (enumsym!=NULL) {
enumsym->usage |= uENUMROOT;
unique=0;
if (fstatic)
enumsym->fnumber=filenum;
}
} /* if */
/* start a new list for the element names */
if ((enumroot=(constvalue_root*)malloc(sizeof(constvalue_root)))==NULL)
error(103); /* insufficient memory (fatal error) */
Expand Down Expand Up @@ -3031,6 +3033,9 @@ static void decl_enum(int vclass,int fstatic)
if (fstatic)
sym->fnumber=filenum;

if (enumroot!=NULL && find_constval_byval(enumroot,value)==NULL)
unique++;

/* add the constant to a separate list as well */
if (enumroot!=NULL) {
sym->usage |= uENUMFIELD;
Expand All @@ -3048,6 +3053,7 @@ static void decl_enum(int vclass,int fstatic)
if (enumsym!=NULL) {
assert((enumsym->usage & uENUMROOT)!=0);
enumsym->addr=value;
enumsym->x.tags.unique=unique;
/* assign the constant list */
assert(enumroot!=NULL);
enumsym->dim.enumlist=enumroot;
Expand Down Expand Up @@ -5891,6 +5897,9 @@ static void doswitch(void)
int swdefault,casecount;
int tok,endtok;
int swtag,csetag;
int enumsymcount,diff;
int save_fline;
symbol *enumsym,*csesym;
cell val;
char *str;
constvalue_root caselist = { NULL, NULL}; /* case list starts empty */
Expand All @@ -5907,6 +5916,17 @@ static void doswitch(void)
lbl_case=0; /* just to avoid a compiler warning */
ffswitch(lbl_table);

save_fline=fline;
enumsym=NULL;
if (swtag!=0) {
constvalue *tagsym=find_tag_byval(swtag);
assert(tagsym->name!=NULL);
enumsymcount=0;
enumsym=findconst(tagsym->name,NULL);
if (enumsym!=NULL && (enumsym->tag!=swtag || enumsym->dim.enumlist==NULL))
enumsym=NULL;
} /* if */

if (matchtoken(tBEGIN)) {
endtok=tEND;
} else {
Expand Down Expand Up @@ -5938,8 +5958,14 @@ static void doswitch(void)
* parse all expressions until that special token.
*/

constexpr(&val,&csetag,NULL);
constexpr(&val,&csetag,&csesym);
check_tagmismatch(swtag,csetag,TRUE,-1);
if (enumsym!=NULL) {
if (csesym!=NULL && csesym->parent==enumsym)
enumsymcount++;
else
enumsym=NULL;
} /* if */
/* Search the insertion point (the table is kept in sorted order, so
* that advanced abstract machines can sift the case table with a
* binary search). Check for duplicate case values at the same time.
Expand Down Expand Up @@ -5967,6 +5993,7 @@ static void doswitch(void)
if (end<=val)
error(50); /* invalid range */
check_tagmismatch(swtag,csetag,TRUE,-1);
enumsym=NULL; /* stop counting the number of covered enum items */
while (++val<=end) {
casecount++;
/* find the new insertion point */
Expand Down Expand Up @@ -6011,6 +6038,29 @@ static void doswitch(void)
} /* switch */
} while (tok!=endtok);

if (enumsym!=NULL && swdefault==FALSE && (diff=enumsym->x.tags.unique-enumsymcount)<=2) {
constvalue_root *enumlist=enumsym->dim.enumlist;
constvalue *val,*prev=NULL,*save_next=NULL;
for (val=enumlist->first; val!=NULL; prev=val,val=val->next) {
/* if multiple enum items share the same value, we only want to pick the first one */
if (prev!=NULL) {
/* see if there's another constvalue before the current one that has the same value */
constvalue *save_next=prev->next;
constvalue *found;
prev->next=NULL;
found=find_constval_byval(enumlist,val->value);
prev->next=save_next;
if (found!=NULL)
continue;
} /* if */
/* check if the value of this constant is handled in switch, if so - continue */
if (find_constval_byval(&caselist,val->value)!=NULL)
continue;
error(241,val->name); /* enum item not handled in switch */
/* */
} /* while */
} /* if */

#if !defined NDEBUG
/* verify that the case table is sorted (unfortunatly, duplicates can
* occur; there really shouldn't be duplicate cases, but the compiler
Expand Down
3 changes: 2 additions & 1 deletion source/compiler/sc5.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ static char *warnmsg[] = {
/*237*/ "user warning: %s\n",
/*238*/ "meaningless combination of class specifiers (%s)\n",
/*239*/ "literal array/string passed to a non-const parameter\n",
/*240*/ "previously assigned value is never used (symbol \"%s\")\n"
/*240*/ "previously assigned value is never used (symbol \"%s\")\n",
/*241*/ "enum item \"%s\" not handled in switch\n"
};

static char *noticemsg[] = {
Expand Down
7 changes: 7 additions & 0 deletions source/compiler/tests/warning_241.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
'test_type': 'output_check',
'errors': """
warning_241.pwn(37) : warning 241: enum item "CONST2_3" not handled in switch
warning_241.pwn(37) : warning 241: enum item "CONST2_5" not handled in switch
"""
}
53 changes: 53 additions & 0 deletions source/compiler/tests/warning_241.pwn
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
enum
{
CONST1_1,
CONST1_2,
CONST1_3,
CONST1_4
};

enum eNamedEnum
{
CONST2_1,
CONST2_2,
CONST2_3,
CONST2_4 = CONST2_3,
CONST2_5
};

main()
{
new var1 = CONST1_1;
new eNamedEnum:var2 = CONST2_1;

switch (var1)
{
// Warning 241 should NOT be printed in this case, as the constants
// belong to an unnamed (anonymous) enumeration.
case CONST1_1, CONST1_2: {}
}

switch (var2)
{
// Two or less items of a named enum are not covered by a switch
// statement; warning 241 must be printed in this case.
// Also, 'CONST2_4' has the same value as 'CONST2_3', so the said
// warning must be printed only for 'CONST2_3' and 'CONST2_5'.
case CONST2_1, CONST2_2: {}
}

switch (var2)
{
// There is a default case, which means all possible values are covered,
// so warning 241 should NOT be printed in this case.
case CONST2_1, CONST2_2: {}
default: {}
}

switch (var2)
{
// More than two enum items are missing, which might be intentional,
// so warning 241 should NOT be printed in this case.
case CONST2_1: {}
}
}