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:
parent
5537b61e6a
commit
c0a2021d9a
|
@ -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 ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user