In switch statements, do only print a warning about missing case labels if
there are no regular labels and no default label. git-svn-id: svn://svn.cc65.org/cc65/trunk@467 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
110
src/cc65/stmt.c
110
src/cc65/stmt.c
@@ -265,24 +265,26 @@ static void docontinue (void)
|
|||||||
static void cascadeswitch (struct expent* eval)
|
static void cascadeswitch (struct expent* eval)
|
||||||
/* Handle a switch statement for chars with a cmp cascade for the selector */
|
/* Handle a switch statement for chars with a cmp cascade for the selector */
|
||||||
{
|
{
|
||||||
unsigned exitlab; /* Exit label */
|
unsigned ExitLab; /* Exit label */
|
||||||
unsigned nextlab; /* Next case label */
|
unsigned NextLab; /* Next case label */
|
||||||
unsigned codelab; /* Label that starts the actual selector code */
|
unsigned CodeLab; /* Label that starts the actual selector code */
|
||||||
int havebreak; /* Remember if we exited with break */
|
int HaveBreak; /* Remember if we exited with break */
|
||||||
|
int HaveDefault; /* Remember if we had a default label */
|
||||||
int lcount; /* Label count */
|
int lcount; /* Label count */
|
||||||
unsigned flags; /* Code generator flags */
|
unsigned Flags; /* Code generator flags */
|
||||||
struct expent lval; /* Case label expression */
|
struct expent lval; /* Case label expression */
|
||||||
long val; /* Case label value */
|
long Val; /* Case label value */
|
||||||
|
|
||||||
|
|
||||||
/* Create a loop so we may break out, init labels */
|
/* Create a loop so we may break out, init labels */
|
||||||
exitlab = GetLabel ();
|
ExitLab = GetLabel ();
|
||||||
AddLoop (oursp, 0, exitlab, 0, 0);
|
AddLoop (oursp, 0, ExitLab, 0, 0);
|
||||||
|
|
||||||
/* Setup some variables needed in the loop below */
|
/* Setup some variables needed in the loop below */
|
||||||
flags = TypeOf (eval->e_tptr) | CF_CONST | CF_FORCECHAR;
|
Flags = TypeOf (eval->e_tptr) | CF_CONST | CF_FORCECHAR;
|
||||||
codelab = nextlab = 0;
|
CodeLab = NextLab = 0;
|
||||||
havebreak = 1;
|
HaveBreak = 1;
|
||||||
|
HaveDefault = 0;
|
||||||
|
|
||||||
/* Parse the labels */
|
/* Parse the labels */
|
||||||
lcount = 0;
|
lcount = 0;
|
||||||
@@ -293,18 +295,18 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
/* If the code for the previous selector did not end with a
|
/* If the code for the previous selector did not end with a
|
||||||
* break statement, we must jump over the next selector test.
|
* break statement, we must jump over the next selector test.
|
||||||
*/
|
*/
|
||||||
if (!havebreak) {
|
if (!HaveBreak) {
|
||||||
/* Define a label for the code */
|
/* Define a label for the code */
|
||||||
if (codelab == 0) {
|
if (CodeLab == 0) {
|
||||||
codelab = GetLabel ();
|
CodeLab = GetLabel ();
|
||||||
}
|
}
|
||||||
g_jump (codelab);
|
g_jump (CodeLab);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have a cascade label, emit it */
|
/* If we have a cascade label, emit it */
|
||||||
if (nextlab) {
|
if (NextLab) {
|
||||||
g_defloclabel (nextlab);
|
g_defloclabel (NextLab);
|
||||||
nextlab = 0;
|
NextLab = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (curtok == TOK_CASE || curtok == TOK_DEFAULT) {
|
while (curtok == TOK_CASE || curtok == TOK_DEFAULT) {
|
||||||
@@ -325,30 +327,30 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check the range of the expression */
|
/* Check the range of the expression */
|
||||||
val = lval.e_const;
|
Val = lval.e_const;
|
||||||
switch (*eval->e_tptr) {
|
switch (*eval->e_tptr) {
|
||||||
|
|
||||||
case T_SCHAR:
|
case T_SCHAR:
|
||||||
/* Signed char */
|
/* Signed char */
|
||||||
if (val < -128 || val > 127) {
|
if (Val < -128 || Val > 127) {
|
||||||
Error ("Range error");
|
Error ("Range error");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_UCHAR:
|
case T_UCHAR:
|
||||||
if (val < 0 || val > 255) {
|
if (Val < 0 || Val > 255) {
|
||||||
Error ("Range error");
|
Error ("Range error");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_INT:
|
case T_INT:
|
||||||
if (val < -32768 || val > 32767) {
|
if (Val < -32768 || Val > 32767) {
|
||||||
Error ("Range error");
|
Error ("Range error");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_UINT:
|
case T_UINT:
|
||||||
if (val < 0 || val > 65535) {
|
if (Val < 0 || Val > 65535) {
|
||||||
Error ("Range error");
|
Error ("Range error");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -361,23 +363,23 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
ConsumeColon ();
|
ConsumeColon ();
|
||||||
|
|
||||||
/* Emit a compare */
|
/* Emit a compare */
|
||||||
g_cmp (flags, val);
|
g_cmp (Flags, Val);
|
||||||
|
|
||||||
/* If another case follows, we will jump to the code if
|
/* If another case follows, we will jump to the code if
|
||||||
* the condition is true.
|
* the condition is true.
|
||||||
*/
|
*/
|
||||||
if (curtok == TOK_CASE) {
|
if (curtok == TOK_CASE) {
|
||||||
/* Create a code label if needed */
|
/* Create a code label if needed */
|
||||||
if (codelab == 0) {
|
if (CodeLab == 0) {
|
||||||
codelab = GetLabel ();
|
CodeLab = GetLabel ();
|
||||||
}
|
}
|
||||||
g_falsejump (CF_NONE, codelab);
|
g_falsejump (CF_NONE, CodeLab);
|
||||||
} else if (curtok != TOK_DEFAULT) {
|
} else if (curtok != TOK_DEFAULT) {
|
||||||
/* No case follows, jump to next selector */
|
/* No case follows, jump to next selector */
|
||||||
if (nextlab == 0) {
|
if (NextLab == 0) {
|
||||||
nextlab = GetLabel ();
|
NextLab = GetLabel ();
|
||||||
}
|
}
|
||||||
g_truejump (CF_NONE, nextlab);
|
g_truejump (CF_NONE, NextLab);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -390,11 +392,14 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
|
|
||||||
/* Handle the pathologic case: DEFAULT followed by CASE */
|
/* Handle the pathologic case: DEFAULT followed by CASE */
|
||||||
if (curtok == TOK_CASE) {
|
if (curtok == TOK_CASE) {
|
||||||
if (codelab == 0) {
|
if (CodeLab == 0) {
|
||||||
codelab = GetLabel ();
|
CodeLab = GetLabel ();
|
||||||
}
|
}
|
||||||
g_jump (codelab);
|
g_jump (CodeLab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remember that we had a default label */
|
||||||
|
HaveDefault = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -402,19 +407,19 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Emit a code label if we have one */
|
/* Emit a code label if we have one */
|
||||||
if (codelab) {
|
if (CodeLab) {
|
||||||
g_defloclabel (codelab);
|
g_defloclabel (CodeLab);
|
||||||
codelab = 0;
|
CodeLab = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse statements */
|
/* Parse statements */
|
||||||
if (curtok != TOK_RCURLY) {
|
if (curtok != TOK_RCURLY) {
|
||||||
havebreak = statement ();
|
HaveBreak = statement ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have any labels */
|
/* Check if we have any labels */
|
||||||
if (lcount == 0) {
|
if (lcount == 0 && !HaveDefault) {
|
||||||
Warning ("No case labels");
|
Warning ("No case labels");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,10 +429,10 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
/* Define the exit label and, if there's a next label left, create this
|
/* Define the exit label and, if there's a next label left, create this
|
||||||
* one, too.
|
* one, too.
|
||||||
*/
|
*/
|
||||||
if (nextlab) {
|
if (NextLab) {
|
||||||
g_defloclabel (nextlab);
|
g_defloclabel (NextLab);
|
||||||
}
|
}
|
||||||
g_defloclabel (exitlab);
|
g_defloclabel (ExitLab);
|
||||||
|
|
||||||
/* End the loop */
|
/* End the loop */
|
||||||
DelLoop ();
|
DelLoop ();
|
||||||
@@ -449,8 +454,9 @@ static void tableswitch (struct expent* eval)
|
|||||||
int label; /* label for case */
|
int label; /* label for case */
|
||||||
int lcase; /* label for compares */
|
int lcase; /* label for compares */
|
||||||
int lcount; /* Label count */
|
int lcount; /* Label count */
|
||||||
int havebreak; /* Last statement has a break */
|
int HaveBreak; /* Last statement has a break */
|
||||||
unsigned flags; /* Code generator flags */
|
int HaveDefault; /* Remember if we had a default label */
|
||||||
|
unsigned Flags; /* Code generator flags */
|
||||||
struct expent lval; /* Case label expression */
|
struct expent lval; /* Case label expression */
|
||||||
struct swent *p;
|
struct swent *p;
|
||||||
struct swent *swtab;
|
struct swent *swtab;
|
||||||
@@ -459,7 +465,8 @@ static void tableswitch (struct expent* eval)
|
|||||||
swtab = xmalloc (CASE_MAX * sizeof (struct swent));
|
swtab = xmalloc (CASE_MAX * sizeof (struct swent));
|
||||||
|
|
||||||
/* Create a look so we may break out, init labels */
|
/* Create a look so we may break out, init labels */
|
||||||
havebreak = 0; /* Keep gcc silent */
|
HaveBreak = 0; /* Keep gcc silent */
|
||||||
|
HaveDefault = 0; /* No default case until now */
|
||||||
dlabel = 0; /* init */
|
dlabel = 0; /* init */
|
||||||
lab = GetLabel (); /* get exit */
|
lab = GetLabel (); /* get exit */
|
||||||
p = swtab;
|
p = swtab;
|
||||||
@@ -488,19 +495,20 @@ static void tableswitch (struct expent* eval)
|
|||||||
} else {
|
} else {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
dlabel = label;
|
dlabel = label;
|
||||||
|
HaveDefault = 1;
|
||||||
}
|
}
|
||||||
ConsumeColon ();
|
ConsumeColon ();
|
||||||
} while (curtok == TOK_CASE || curtok == TOK_DEFAULT);
|
} while (curtok == TOK_CASE || curtok == TOK_DEFAULT);
|
||||||
g_defloclabel (label);
|
g_defloclabel (label);
|
||||||
havebreak = 0;
|
HaveBreak = 0;
|
||||||
}
|
}
|
||||||
if (curtok != TOK_RCURLY) {
|
if (curtok != TOK_RCURLY) {
|
||||||
havebreak = statement ();
|
HaveBreak = statement ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have any labels */
|
/* Check if we have any labels */
|
||||||
if (lcount == 0) {
|
if (lcount == 0 && !HaveDefault) {
|
||||||
Warning ("No case labels");
|
Warning ("No case labels");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +516,7 @@ static void tableswitch (struct expent* eval)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* If the last statement doesn't have a break or return, add one */
|
/* If the last statement doesn't have a break or return, add one */
|
||||||
if (!havebreak) {
|
if (!HaveBreak) {
|
||||||
g_jump (lab);
|
g_jump (lab);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,8 +524,8 @@ static void tableswitch (struct expent* eval)
|
|||||||
g_defloclabel (lcase);
|
g_defloclabel (lcase);
|
||||||
|
|
||||||
/* Create the call to the switch subroutine */
|
/* Create the call to the switch subroutine */
|
||||||
flags = TypeOf (eval->e_tptr);
|
Flags = TypeOf (eval->e_tptr);
|
||||||
g_switch (flags);
|
g_switch (Flags);
|
||||||
|
|
||||||
/* First entry is negative of label count */
|
/* First entry is negative of label count */
|
||||||
g_defdata (CF_INT | CF_CONST, -((int)lcount)-1, 0);
|
g_defdata (CF_INT | CF_CONST, -((int)lcount)-1, 0);
|
||||||
@@ -526,7 +534,7 @@ static void tableswitch (struct expent* eval)
|
|||||||
AddCodeHint ("casetable");
|
AddCodeHint ("casetable");
|
||||||
p = swtab;
|
p = swtab;
|
||||||
while (lcount) {
|
while (lcount) {
|
||||||
g_case (flags, p->sw_lab, p->sw_const); /* Create one label */
|
g_case (Flags, p->sw_lab, p->sw_const); /* Create one label */
|
||||||
--lcount;
|
--lcount;
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user