Fix the "double semicolon" problem where a double semicolon after a statement

that makes the following code unreachable led to an "unreachable code" warning.
This commit is contained in:
Kugel Fuhr
2025-07-18 17:20:00 +02:00
parent b0e10e1f9a
commit 8ac25376a0
3 changed files with 29 additions and 8 deletions

View File

@@ -741,16 +741,28 @@ int StatementBlock (struct SwitchCtrl* Switch)
if (CurTok.Tok != TOK_RCURLY && CurTok.Tok != TOK_CEOF) {
LineInfo* LI1 = UseLineInfo (GetDiagnosticLI ());
int StmtFlags1 = AnyStatement (0, Switch);
int UnreachableWarning = 0;
int Unreachable = 0; /* True if code is unreachable */
int UnreachableWarning = 0; /* True if warning was output */
while (CurTok.Tok != TOK_RCURLY && CurTok.Tok != TOK_CEOF) {
LineInfo* LI2 = UseLineInfo (GetDiagnosticLI ());
int StmtFlags2 = AnyStatement (0, Switch);
if (!UnreachableWarning) {
/* Check if the code is unreachable because of a preceeding
** jump and if the code doesn't have a jump label.
/* If this statement is not already unreachable, check if the
** previous statement made it unreachable.
*/
if ((StmtFlags1 & SF_MASK_UNREACH) != SF_NONE &&
(StmtFlags2 & SF_MASK_LABEL) == SF_NONE) {
if (!Unreachable) {
Unreachable = SF_Unreach (StmtFlags1);
}
/* If the previous statement made this one unreachable, but
** this one has a label, it is not unreachable.
*/
if (Unreachable && SF_Label (StmtFlags2)) {
Unreachable = 0;
}
/* If this statement is unreachable but not the empty
** statement, output a warning.
*/
if (Unreachable && !SF_Empty (StmtFlags2)) {
LIUnreachableCodeWarning (LI2);
UnreachableWarning = 1;
}
@@ -873,7 +885,7 @@ int AnyStatement (int* PendingToken, struct SwitchCtrl* Switch)
case TOK_SEMI:
/* Empty statement. Ignore it */
CheckSemi (PendingToken);
StmtFlags = SF_NONE;
StmtFlags = SF_EMPTY;
break;
case TOK_LCURLY:

View File

@@ -88,6 +88,9 @@ enum {
SF_LABEL_CASE = 0x20000, /* Statement preceeded by case label */
SF_LABEL_DEFAULT = 0x40000, /* Statement preceeded by default label */
SF_MASK_LABEL = 0x70000, /* Mask for any label */
/* And a flag to mark an empty statement */
SF_EMPTY = 0x80000, /* Empty statement */
};
/* Forward */
@@ -137,6 +140,12 @@ static inline int SF_Label (int F)
return (F & SF_MASK_LABEL);
}
static inline int SF_Empty (int F)
/* Check if this is the empty statement */
{
return (F & SF_EMPTY);
}
/*****************************************************************************/

View File

@@ -393,8 +393,8 @@ void SwitchBodyStatement (struct SwitchCtrl* S, LineInfo* LI, int StmtFlags)
/* Handle code without a label in the switch */
if (SC_Label (S) == SC_NONE) {
/* This is a statement that preceedes any switch labels. If the
** switch is not already marked as weird, output and the current
** statement has no label, output a warning about unreachable code.
** switch is not already marked as weird and the current statement
** has no label, output a warning about unreachable code.
*/
if (!SC_IsWeird (S)) {
if (!SF_Label (StmtFlags)) {