1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-08 15:29:37 +00:00

Fixed endlessly repeated disgnostics when there are some certain patterns of syntax errors in a struct/union declaration.

This commit is contained in:
acqn 2023-11-30 00:35:30 +08:00
parent 5537b61e6a
commit c0a2021d9a
3 changed files with 102 additions and 58 deletions

View File

@ -257,6 +257,7 @@ static void Parse (void)
/* Parse the initialization */ /* Parse the initialization */
ParseInit (Sym->Type); ParseInit (Sym->Type);
} else { } else {
/* This is a declaration */ /* This is a declaration */
@ -326,21 +327,19 @@ NextDecl:
} }
} }
/* Function declaration? */ /* Finish the declaration */
if (Sym && IsTypeFunc (Sym->Type)) { if (Sym) {
/* Function definition? */
/* Function */ if (IsTypeFunc (Sym->Type) && CurTok.Tok == TOK_LCURLY) {
if (CurTok.Tok == TOK_SEMI) {
/* Prototype only */
NeedClean = 0;
NextToken ();
} else if (CurTok.Tok == TOK_LCURLY) {
/* ISO C: The type category in a function definition cannot be
** inherited from a typedef.
*/
if (IsTypeFunc (Spec.Type) && TypeCmp (Sym->Type, Spec.Type).C >= TC_EQUAL) { if (IsTypeFunc (Spec.Type) && TypeCmp (Sym->Type, Spec.Type).C >= TC_EQUAL) {
/* ISO C: The type category in a function definition cannot be
** inherited from a typedef.
*/
Error ("Function cannot be defined with a typedef"); Error ("Function cannot be defined with a typedef");
} else if (comma) { } else if (comma) {
/* ISO C: A function definition cannot shall its return type
** specifier with other declarators.
*/
Error ("';' expected after top level declarator"); Error ("';' expected after top level declarator");
} }
@ -350,30 +349,19 @@ NextDecl:
/* Make sure we aren't omitting any work */ /* Make sure we aren't omitting any work */
CheckDeferredOpAllDone (); CheckDeferredOpAllDone ();
} } else {
} else {
if (Sym) {
/* Must be followed by a semicolon */ /* Must be followed by a semicolon */
if (CurTok.Tok != TOK_SEMI) { if (ConsumeSemi ()) {
NeedClean = 0;
} else {
NeedClean = -1; NeedClean = -1;
} }
ConsumeSemi ();
} }
} }
/* Try some smart error recovery */ /* Try some smart error recovery */
if (PrevErrorCount != ErrorCount && NeedClean < 0) { if (PrevErrorCount != ErrorCount && NeedClean < 0) {
/* Some fix point tokens that are used for error recovery */ SmartErrorSkip (1);
static const token_t TokenList[] = { TOK_SEMI, TOK_RCURLY };
SmartErrorSkip ();
SkipTokens (TokenList, sizeof (TokenList) / sizeof (TokenList[0]));
if (CurTok.Tok == TOK_SEMI || CurTok.Tok == TOK_RCURLY) {
NextToken ();
}
} }
} }

View File

@ -117,11 +117,22 @@ static int CloseBrace (Collection* C, token_t Tok)
int SmartErrorSkip (void) int SmartErrorSkip (int WholeDecl)
/* Try some smart error recovery. Skip tokens until either a comma or semicolon /* Try some smart error recovery.
** that is not enclosed in an open parenthesis/bracket/curly brace, or until an **
** unpaired right parenthesis/bracket/curly brace is reached. Return 0 if it is ** - If WholeDecl is 0:
** the former case, or -1 if it is the latter case. */ ** Skip tokens until a comma or closing curly brace that is not enclosed in
** an open parenthesis/bracket/curly brace, or until a semicolon, EOF or
** unpaired right parenthesis/bracket/curly brace is reached.
**
** - If WholeDecl is non-0:
** Skip tokens until a closing curly brace that is not enclosed in an open
** parenthesis/bracket/curly brace, or until a semicolon or EOF is reached.
**
** Return 0 if this exits as soon as it reaches an EOF. Return 0 as well if
** this exits with no open parentheses/brackets/curly braces. Otherwise, return
** -1.
*/
{ {
Collection C = AUTO_COLLECTION_INITIALIZER; Collection C = AUTO_COLLECTION_INITIALIZER;
int Res = 0; int Res = 0;
@ -142,31 +153,41 @@ int SmartErrorSkip (void)
case TOK_RPAREN: case TOK_RPAREN:
case TOK_RBRACK: case TOK_RBRACK:
if (CloseBrace (&C, CurTok.Tok)) { if (CloseBrace (&C, CurTok.Tok) < 0) {
Res = -1; if (!WholeDecl) {
goto ExitPoint; Res = -1;
goto ExitPoint;
}
NextToken ();
} }
break; break;
case TOK_RCURLY: case TOK_RCURLY:
if (CloseBrace (&C, CurTok.Tok)) { if (CloseBrace (&C, CurTok.Tok) < 0) {
Res = -1; if (!WholeDecl) {
goto ExitPoint; Res = -1;
goto ExitPoint;
}
NextToken ();
} else if (CollCount (&C) == 0) { } else if (CollCount (&C) == 0) {
goto ExitPoint; goto ExitPoint;
} }
break; break;
case TOK_COMMA: case TOK_COMMA:
if (CollCount (&C) == 0) { if (CollCount (&C) == 0 && !WholeDecl) {
goto ExitPoint; goto ExitPoint;
} }
NextToken (); NextToken ();
break; break;
case TOK_SEMI: case TOK_SEMI:
if (CollCount (&C) != 0) {
Res = -1;
}
goto ExitPoint;
case TOK_CEOF: case TOK_CEOF:
Res = -1;
goto ExitPoint; goto ExitPoint;
default: default:
@ -1058,8 +1079,9 @@ static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags)
while (CurTok.Tok != TOK_RCURLY) { while (CurTok.Tok != TOK_RCURLY) {
/* Get the type of the entry */ /* Get the type of the entry */
DeclSpec Spec; DeclSpec Spec;
int SignednessSpecified = 0; int SignednessSpecified = 0;
int NeedClean = 0;
/* Check for a _Static_assert */ /* Check for a _Static_assert */
if (CurTok.Tok == TOK_STATIC_ASSERT) { if (CurTok.Tok == TOK_STATIC_ASSERT) {
@ -1076,7 +1098,7 @@ static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags)
Declarator Decl; Declarator Decl;
/* Get type and name of the struct field */ /* Get type and name of the struct field */
ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT); NeedClean = ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
/* Check for a bit-field declaration */ /* Check for a bit-field declaration */
FieldWidth = ParseFieldWidth (&Decl); FieldWidth = ParseFieldWidth (&Decl);
@ -1172,7 +1194,18 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
} }
NextToken (); NextToken ();
} }
ConsumeSemi ();
/* Must be followed by a semicolon */
if (NeedClean >= 0 && ConsumeSemi ()) {
NeedClean = 0;
} else {
NeedClean = -1;
}
/* Try some smart error recovery */
if (NeedClean < 0) {
SmartErrorSkip (1);
}
} }
/* Skip the closing brace */ /* Skip the closing brace */
@ -1236,8 +1269,9 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags)
while (CurTok.Tok != TOK_RCURLY) { while (CurTok.Tok != TOK_RCURLY) {
/* Get the type of the entry */ /* Get the type of the entry */
DeclSpec Spec; DeclSpec Spec;
int SignednessSpecified = 0; int SignednessSpecified = 0;
int NeedClean = 0;
/* Check for a _Static_assert */ /* Check for a _Static_assert */
if (CurTok.Tok == TOK_STATIC_ASSERT) { if (CurTok.Tok == TOK_STATIC_ASSERT) {
@ -1262,7 +1296,7 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags)
} }
/* Get type and name of the struct field */ /* Get type and name of the struct field */
ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT); NeedClean = ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
/* Check for a bit-field declaration */ /* Check for a bit-field declaration */
FieldWidth = ParseFieldWidth (&Decl); FieldWidth = ParseFieldWidth (&Decl);
@ -1403,7 +1437,18 @@ NextMember: if (CurTok.Tok != TOK_COMMA) {
} }
NextToken (); NextToken ();
} }
ConsumeSemi ();
/* Must be followed by a semicolon */
if (NeedClean >= 0 && ConsumeSemi ()) {
NeedClean = 0;
} else {
NeedClean = -1;
}
/* Try some smart error recovery */
if (NeedClean < 0) {
SmartErrorSkip (1);
}
} }
if (BitOffs > 0) { if (BitOffs > 0) {
@ -1778,7 +1823,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
Error ("Identifier expected for parameter name"); Error ("Identifier expected for parameter name");
/* Try some smart error recovery */ /* Try some smart error recovery */
if (SmartErrorSkip () < 0) { if (SmartErrorSkip (0) < 0) {
break; break;
} }
} }
@ -1868,7 +1913,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
if (PrevErrorCount != ErrorCount && CurTok.Tok != TOK_LCURLY) { if (PrevErrorCount != ErrorCount && CurTok.Tok != TOK_LCURLY) {
/* Try some smart error recovery */ /* Try some smart error recovery */
SmartErrorSkip (); SmartErrorSkip (0);
} }
} }
@ -1953,7 +1998,7 @@ static void ParseAnsiParamList (FuncDesc* F)
if (PrevErrorCount != ErrorCount) { if (PrevErrorCount != ErrorCount) {
/* Try some smart error recovery */ /* Try some smart error recovery */
if (SmartErrorSkip () < 0) { if (SmartErrorSkip (0) < 0) {
break; break;
} }
} }
@ -2335,7 +2380,7 @@ int ParseDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode)
/* Try some smart error recovery */ /* Try some smart error recovery */
if (CurTok.Tok != TOK_LCURLY || !IsTypeFunc (D->Type)) { if (CurTok.Tok != TOK_LCURLY || !IsTypeFunc (D->Type)) {
return SmartErrorSkip (); return SmartErrorSkip (0);
} }
} }

View File

@ -128,11 +128,22 @@ typedef enum {
int SmartErrorSkip (void); int SmartErrorSkip (int WholeDecl);
/* Try some smart error recovery. Skip tokens until either a comma or semicolon /* Try some smart error recovery.
** that is not enclosed in an open parenthesis/bracket/curly brace, or until an **
** unpaired right parenthesis/bracket/curly brace is reached. Return 0 if it is ** - If WholeDecl is 0:
** the former case, or -1 if it is the latter case. */ ** Skip tokens until a comma or closing curly brace that is not enclosed in
** an open parenthesis/bracket/curly brace, or until a semicolon, EOF or
** unpaired right parenthesis/bracket/curly brace is reached.
**
** - If WholeDecl is non-0:
** Skip tokens until a closing curly brace that is not enclosed in an open
** parenthesis/bracket/curly brace, or until a semicolon or EOF is reached.
**
** Return 0 if this exits as soon as it reaches an EOF. Return 0 as well if
** this exits with no open parentheses/brackets/curly braces. Otherwise, return
** -1.
*/
Type* ParseType (Type* Type); Type* ParseType (Type* Type);
/* Parse a complete type specification */ /* Parse a complete type specification */