mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 00:29:31 +00:00
Invalid code was generated for a switch statement with no case labels.
git-svn-id: svn://svn.cc65.org/cc65/trunk@3191 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
f1617b3837
commit
2414d6cd11
@ -69,6 +69,8 @@ void SwitchStatement (void)
|
||||
ExprDesc CaseExpr; /* Case label expression */
|
||||
type SwitchExprType; /* Basic switch expression type */
|
||||
CodeMark CaseCodeStart; /* Start of code marker */
|
||||
CodeMark SwitchCodeStart; /* Start of switch code */
|
||||
CodeMark SwitchCodeEnd; /* End of switch code */
|
||||
unsigned Depth; /* Number of bytes the selector type has */
|
||||
unsigned ExitLabel; /* Exit label */
|
||||
unsigned CaseLabel; /* Label for case */
|
||||
@ -91,7 +93,6 @@ void SwitchStatement (void)
|
||||
/* To avoid any compiler errors, make the expression a valid int */
|
||||
ED_MakeConstAbsInt (&SwitchExpr, 1);
|
||||
}
|
||||
/* Load the expression into the primary register */
|
||||
ConsumeRParen ();
|
||||
|
||||
/* Add a jump to the switch code. This jump is usually unnecessary,
|
||||
@ -119,7 +120,7 @@ void SwitchStatement (void)
|
||||
|
||||
/* Get the number of bytes the selector type has */
|
||||
Depth = SizeOf (SwitchExpr.Type);
|
||||
CHECK (Depth == 1 || Depth == 2 || Depth == 4);
|
||||
CHECK (Depth == SIZEOF_CHAR || Depth == SIZEOF_INT || Depth == SIZEOF_LONG);
|
||||
|
||||
/* Get the exit label for the switch statement */
|
||||
ExitLabel = GetLocalLabel ();
|
||||
@ -230,36 +231,32 @@ void SwitchStatement (void)
|
||||
|
||||
Warning ("No case labels");
|
||||
|
||||
} else {
|
||||
|
||||
CodeMark SwitchCodeStart, SwitchCodeEnd;
|
||||
|
||||
/* If the last statement did not have a break, we may have an open
|
||||
* label (maybe from an if or similar). Emitting code and then moving
|
||||
* this code to the top will also move the label to the top which is
|
||||
* wrong. So if the last statement did not have a break (which would
|
||||
* carry the label), add a jump to the exit. If it is useless, the
|
||||
* optimizer will remove it later.
|
||||
*/
|
||||
if (!HaveBreak) {
|
||||
g_jump (ExitLabel);
|
||||
}
|
||||
|
||||
/* Remember the current position */
|
||||
GetCodePos (&SwitchCodeStart);
|
||||
|
||||
/* Output the switch code label */
|
||||
g_defcodelabel (SwitchCodeLabel);
|
||||
|
||||
/* Generate code */
|
||||
g_switch (Nodes, DefaultLabel? DefaultLabel : ExitLabel, Depth);
|
||||
|
||||
/* Move the code to the front */
|
||||
GetCodePos (&SwitchCodeEnd);
|
||||
MoveCode (&SwitchCodeStart, &SwitchCodeEnd, &CaseCodeStart);
|
||||
|
||||
}
|
||||
|
||||
/* If the last statement did not have a break, we may have an open
|
||||
* label (maybe from an if or similar). Emitting code and then moving
|
||||
* this code to the top will also move the label to the top which is
|
||||
* wrong. So if the last statement did not have a break (which would
|
||||
* carry the label), add a jump to the exit. If it is useless, the
|
||||
* optimizer will remove it later.
|
||||
*/
|
||||
if (!HaveBreak) {
|
||||
g_jump (ExitLabel);
|
||||
}
|
||||
|
||||
/* Remember the current position */
|
||||
GetCodePos (&SwitchCodeStart);
|
||||
|
||||
/* Output the switch code label */
|
||||
g_defcodelabel (SwitchCodeLabel);
|
||||
|
||||
/* Generate code */
|
||||
g_switch (Nodes, DefaultLabel? DefaultLabel : ExitLabel, Depth);
|
||||
|
||||
/* Move the code to the front */
|
||||
GetCodePos (&SwitchCodeEnd);
|
||||
MoveCode (&SwitchCodeStart, &SwitchCodeEnd, &CaseCodeStart);
|
||||
|
||||
/* Define the exit label */
|
||||
g_defcodelabel (ExitLabel);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user