Improved error recovery with type cast and sizeof.

This commit is contained in:
acqn 2023-12-10 15:43:24 +08:00
parent a1a060c291
commit cadf8012f6
6 changed files with 83 additions and 32 deletions

View File

@ -2166,20 +2166,41 @@ static void DirectDecl (DeclSpec* Spec, Declarator* D, declmode_t Mode)
Type* ParseType (Type* T)
/* Parse a complete type specification */
/* Parse a complete type specification in parentheses */
{
DeclSpec Spec;
Declarator Decl;
int NeedClean = -1;
/* Skip the left paren */
NextToken ();
/* Get a type without a default */
InitDeclSpec (&Spec);
ParseTypeSpec (&Spec, TS_DEFAULT_TYPE_NONE);
/* Parse additional declarators */
ParseDecl (&Spec, &Decl, DM_NO_IDENT);
/* Only parse further if there is a type specifier */
if ((Spec.Flags & DS_TYPE_MASK) != DS_NONE) {
/* Parse additional declarators */
NeedClean = ParseDecl (&Spec, &Decl, DM_NO_IDENT);
/* Copy the type to the target buffer */
TypeCopy (T, Decl.Type);
/* Copy the type to the target buffer */
TypeCopy (T, Decl.Type);
} else {
/* Fail-safe */
TypeCopy (T, type_int);
}
/* Try some smart error recovery */
if (NeedClean < 0) {
SimpleErrorSkip ();
}
/* Closing paren */
if (!ConsumeRParen ()) {
SimpleErrorSkip ();
NextToken ();
}
/* Return a pointer to the target buffer */
return T;

View File

@ -135,7 +135,7 @@ typedef enum {
Type* ParseType (Type* Type);
/* Parse a complete type specification */
/* Parse a complete type specification in parentheses */
int ParseDecl (DeclSpec* Spec, Declarator* D, declmode_t Mode);
/* Parse a variable, type or function declarator. Return -1 if this stops at

View File

@ -1415,24 +1415,8 @@ static void Primary (ExprDesc* E)
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
if ((Spec.Flags & DS_TYPE_MASK) != DS_NONE) {
/* Recognized but not supported */
Error ("Mixed declarations and code are not supported in cc65");
while (CurTok.Tok != TOK_SEMI) {
Declarator Decl;
/* Parse one declaration */
ParseDecl (&Spec, &Decl, DM_IDENT_OR_EMPTY);
if (CurTok.Tok == TOK_ASSIGN) {
NextToken ();
ParseInit (Decl.Type);
}
if (CurTok.Tok == TOK_COMMA) {
NextToken ();
} else {
break;
}
}
SmartErrorSkip (0);
} else {
Error ("Expression expected");
E->Flags |= E_EVAL_MAYBE_UNUSED;
@ -2089,9 +2073,7 @@ void hie10 (ExprDesc* Expr)
NextToken ();
if (TypeSpecAhead ()) {
Type T[MAXTYPELEN];
NextToken ();
Size = ExprCheckedSizeOf (ParseType (T));
ConsumeRParen ();
} else {
/* Remember the output queue pointer */
CodeMark Mark;

View File

@ -1392,6 +1392,55 @@ ExitPoint:
int SimpleErrorSkip (void)
/* Skip tokens until an EOF or unpaired right parenthesis/bracket/curly brace
** is reached. Return 0 If this exits at an EOF. Otherwise return -1.
*/
{
Collection C = AUTO_COLLECTION_INITIALIZER;
int Res = 0;
/* Some fix point tokens that are used for error recovery */
static const token_t TokenList[] = {
TOK_LPAREN, TOK_RPAREN, TOK_LBRACK, TOK_RBRACK, TOK_LCURLY, TOK_RCURLY };
while (CurTok.Tok != TOK_CEOF) {
SkipTokens (TokenList, sizeof (TokenList) / sizeof (TokenList[0]));
switch (CurTok.Tok) {
case TOK_LPAREN:
case TOK_LBRACK:
case TOK_LCURLY:
OpenBrace (&C, CurTok.Tok);
break;
case TOK_RPAREN:
case TOK_RBRACK:
case TOK_RCURLY:
if (CloseBrace (&C, CurTok.Tok) < 0) {
/* Found a terminator */
Res = -1;
goto ExitPoint;
}
break;
case TOK_CEOF:
/* We cannot go any farther */
Res = 0;
goto ExitPoint;
default:
Internal ("Unexpected token: %02X", (unsigned)CurTok.Tok);
}
}
ExitPoint:
DoneCollection (&C);
return Res;
}
int Consume (token_t Token, const char* ErrorMsg)
/* Eat token if it is the next in the input stream, otherwise print an error
** message. Returns true if the token was found and false otherwise.

View File

@ -339,6 +339,11 @@ int SmartErrorSkip (int TillEnd);
** If this exits at a non-EOF without consuming it.
*/
int SimpleErrorSkip (void);
/* Skip tokens until an EOF or unpaired right parenthesis/bracket/curly brace
** is reached. Return 0 If this exits at an EOF. Otherwise return -1.
*/
int Consume (token_t Token, const char* ErrorMsg);
/* Eat token if it is the next in the input stream, otherwise print an error
** message. Returns true if the token was found and false otherwise.

View File

@ -321,15 +321,9 @@ void TypeCast (ExprDesc* Expr)
{
Type NewType[MAXTYPELEN];
/* Skip the left paren */
NextToken ();
/* Read the type */
/* Read the type enclosed in parentheses */
ParseType (NewType);
/* Closing paren */
ConsumeRParen ();
/* Read the expression we have to cast */
hie10 (Expr);