mirror of
https://github.com/cc65/cc65.git
synced 2024-09-21 18:47:31 +00:00
Improved error recovery with type cast and sizeof.
This commit is contained in:
parent
a1a060c291
commit
cadf8012f6
@ -2166,20 +2166,41 @@ static void DirectDecl (DeclSpec* Spec, Declarator* D, declmode_t Mode)
|
|||||||
|
|
||||||
|
|
||||||
Type* ParseType (Type* T)
|
Type* ParseType (Type* T)
|
||||||
/* Parse a complete type specification */
|
/* Parse a complete type specification in parentheses */
|
||||||
{
|
{
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
Declarator Decl;
|
Declarator Decl;
|
||||||
|
int NeedClean = -1;
|
||||||
|
|
||||||
|
/* Skip the left paren */
|
||||||
|
NextToken ();
|
||||||
|
|
||||||
/* Get a type without a default */
|
/* Get a type without a default */
|
||||||
InitDeclSpec (&Spec);
|
InitDeclSpec (&Spec);
|
||||||
ParseTypeSpec (&Spec, TS_DEFAULT_TYPE_NONE);
|
ParseTypeSpec (&Spec, TS_DEFAULT_TYPE_NONE);
|
||||||
|
|
||||||
/* Parse additional declarators */
|
/* Only parse further if there is a type specifier */
|
||||||
ParseDecl (&Spec, &Decl, DM_NO_IDENT);
|
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 */
|
/* Copy the type to the target buffer */
|
||||||
TypeCopy (T, Decl.Type);
|
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 a pointer to the target buffer */
|
||||||
return T;
|
return T;
|
||||||
|
@ -135,7 +135,7 @@ typedef enum {
|
|||||||
|
|
||||||
|
|
||||||
Type* ParseType (Type* Type);
|
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);
|
int ParseDecl (DeclSpec* Spec, Declarator* D, declmode_t Mode);
|
||||||
/* Parse a variable, type or function declarator. Return -1 if this stops at
|
/* Parse a variable, type or function declarator. Return -1 if this stops at
|
||||||
|
@ -1415,24 +1415,8 @@ static void Primary (ExprDesc* E)
|
|||||||
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
|
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
|
||||||
|
|
||||||
if ((Spec.Flags & DS_TYPE_MASK) != DS_NONE) {
|
if ((Spec.Flags & DS_TYPE_MASK) != DS_NONE) {
|
||||||
/* Recognized but not supported */
|
|
||||||
Error ("Mixed declarations and code are not supported in cc65");
|
Error ("Mixed declarations and code are not supported in cc65");
|
||||||
|
SmartErrorSkip (0);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Error ("Expression expected");
|
Error ("Expression expected");
|
||||||
E->Flags |= E_EVAL_MAYBE_UNUSED;
|
E->Flags |= E_EVAL_MAYBE_UNUSED;
|
||||||
@ -2089,9 +2073,7 @@ void hie10 (ExprDesc* Expr)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
if (TypeSpecAhead ()) {
|
if (TypeSpecAhead ()) {
|
||||||
Type T[MAXTYPELEN];
|
Type T[MAXTYPELEN];
|
||||||
NextToken ();
|
|
||||||
Size = ExprCheckedSizeOf (ParseType (T));
|
Size = ExprCheckedSizeOf (ParseType (T));
|
||||||
ConsumeRParen ();
|
|
||||||
} else {
|
} else {
|
||||||
/* Remember the output queue pointer */
|
/* Remember the output queue pointer */
|
||||||
CodeMark Mark;
|
CodeMark Mark;
|
||||||
|
@ -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)
|
int Consume (token_t Token, const char* ErrorMsg)
|
||||||
/* Eat token if it is the next in the input stream, otherwise print an error
|
/* 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.
|
** message. Returns true if the token was found and false otherwise.
|
||||||
|
@ -339,6 +339,11 @@ int SmartErrorSkip (int TillEnd);
|
|||||||
** If this exits at a non-EOF without consuming it.
|
** 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);
|
int Consume (token_t Token, const char* ErrorMsg);
|
||||||
/* Eat token if it is the next in the input stream, otherwise print an error
|
/* 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.
|
** message. Returns true if the token was found and false otherwise.
|
||||||
|
@ -321,15 +321,9 @@ void TypeCast (ExprDesc* Expr)
|
|||||||
{
|
{
|
||||||
Type NewType[MAXTYPELEN];
|
Type NewType[MAXTYPELEN];
|
||||||
|
|
||||||
/* Skip the left paren */
|
/* Read the type enclosed in parentheses */
|
||||||
NextToken ();
|
|
||||||
|
|
||||||
/* Read the type */
|
|
||||||
ParseType (NewType);
|
ParseType (NewType);
|
||||||
|
|
||||||
/* Closing paren */
|
|
||||||
ConsumeRParen ();
|
|
||||||
|
|
||||||
/* Read the expression we have to cast */
|
/* Read the expression we have to cast */
|
||||||
hie10 (Expr);
|
hie10 (Expr);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user