Merge pull request #2201 from acqn/Diagnostics

[cc65] Improved diagnostics
This commit is contained in:
Bob Andrews
2023-10-05 03:19:31 +02:00
committed by GitHub
5 changed files with 49 additions and 12 deletions

View File

@@ -178,7 +178,7 @@ static void Parse (void)
** or semicolon, it must be followed by a function body. ** or semicolon, it must be followed by a function body.
*/ */
if ((Decl.StorageClass & SC_FUNC) != 0) { if ((Decl.StorageClass & SC_FUNC) != 0) {
if (CurTok.Tok != TOK_COMMA && CurTok.Tok != TOK_SEMI) { if (CurTok.Tok == TOK_LCURLY) {
/* A definition */ /* A definition */
Decl.StorageClass |= SC_DEF; Decl.StorageClass |= SC_DEF;
@@ -190,6 +190,10 @@ static void Parse (void)
FuncDef->Flags = (FuncDef->Flags & ~FD_EMPTY) | FD_VOID_PARAM; FuncDef->Flags = (FuncDef->Flags & ~FD_EMPTY) | FD_VOID_PARAM;
} }
} else { } else {
if (CurTok.Tok != TOK_COMMA && CurTok.Tok != TOK_SEMI) {
Error ("Expected ',' or ';' after top level declarator");
}
/* Just a declaration */ /* Just a declaration */
Decl.StorageClass |= SC_DECL; Decl.StorageClass |= SC_DECL;
} }
@@ -325,7 +329,7 @@ static void Parse (void)
if (CurTok.Tok == TOK_SEMI) { if (CurTok.Tok == TOK_SEMI) {
/* Prototype only */ /* Prototype only */
NextToken (); NextToken ();
} else { } else if (CurTok.Tok == TOK_LCURLY) {
/* Parse the function body */ /* Parse the function body */
NewFunc (Sym, FuncDef); NewFunc (Sym, FuncDef);

View File

@@ -1452,7 +1452,7 @@ static void ParseTypeSpec (DeclSpec* D, typespec_t TSFlags, int* SignednessSpeci
NextToken (); NextToken ();
} else { } else {
if (CurTok.Tok != TOK_LCURLY) { if (CurTok.Tok != TOK_LCURLY) {
Error ("Identifier expected"); Error ("Identifier expected for enum tag name");
} }
AnonName (Ident, "enum"); AnonName (Ident, "enum");
} }
@@ -1504,8 +1504,8 @@ static void ParseTypeSpec (DeclSpec* D, typespec_t TSFlags, int* SignednessSpeci
/* FALL THROUGH */ /* FALL THROUGH */
default: default:
if ((TSFlags & TS_MASK_DEFAULT_TYPE) != TS_DEFAULT_TYPE_INT) { if ((TSFlags & TS_MASK_DEFAULT_TYPE) == TS_DEFAULT_TYPE_NONE) {
Error ("Type expected"); D->Flags |= DS_NO_TYPE;
D->Type[0].C = T_INT; D->Type[0].C = T_INT;
D->Type[1].C = T_END; D->Type[1].C = T_END;
} else { } else {
@@ -1553,8 +1553,7 @@ static const Type* ParamTypeCvt (Type* T)
static void ParseOldStyleParamList (FuncDesc* F) static void ParseOldStyleParamList (FuncDesc* F)
/* Parse an old-style (K&R) parameter list */ /* Parse an old-style (K&R) parameter list */
{ {
/* Some fix point tokens that are used for error recovery */ unsigned PrevErrorCount = ErrorCount;
static const token_t TokenList[] = { TOK_COMMA, TOK_RPAREN, TOK_SEMI };
/* Parse params */ /* Parse params */
while (CurTok.Tok != TOK_RPAREN) { while (CurTok.Tok != TOK_RPAREN) {
@@ -1572,8 +1571,11 @@ static void ParseOldStyleParamList (FuncDesc* F)
NextToken (); NextToken ();
} else { } else {
/* Some fix point tokens that are used for error recovery */
static const token_t TokenList[] = { TOK_COMMA, TOK_RPAREN, TOK_SEMI };
/* Not a parameter name */ /* Not a parameter name */
Error ("Identifier expected"); Error ("Identifier expected for parameter name");
/* Try some smart error recovery */ /* Try some smart error recovery */
SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0])); SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0]));
@@ -1608,6 +1610,12 @@ static void ParseOldStyleParamList (FuncDesc* F)
Error ("Illegal storage class"); Error ("Illegal storage class");
} }
/* Type must be specified */
if ((Spec.Flags & DS_NO_TYPE) != 0) {
Error ("Expected declaration specifiers");
break;
}
/* Parse a comma separated variable list */ /* Parse a comma separated variable list */
while (1) { while (1) {
@@ -1655,6 +1663,14 @@ static void ParseOldStyleParamList (FuncDesc* F)
/* Variable list must be semicolon terminated */ /* Variable list must be semicolon terminated */
ConsumeSemi (); ConsumeSemi ();
} }
if (PrevErrorCount != ErrorCount) {
/* Some fix point tokens that are used for error recovery */
static const token_t TokenList[] = { TOK_COMMA, TOK_SEMI };
/* Try some smart error recovery */
SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0]));
}
} }
@@ -1689,6 +1705,11 @@ static void ParseAnsiParamList (FuncDesc* F)
Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF; Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
} }
/* Type must be specified */
if ((Spec.Flags & DS_NO_TYPE) != 0) {
Error ("Type specifier missing");
}
/* Warn about new local type declaration */ /* Warn about new local type declaration */
if ((Spec.Flags & DS_NEW_TYPE_DECL) != 0) { if ((Spec.Flags & DS_NEW_TYPE_DECL) != 0) {
Warning ("'%s' will be invisible out of this function", Warning ("'%s' will be invisible out of this function",
@@ -1870,12 +1891,21 @@ static void DirectDecl (const DeclSpec* Spec, Declarator* D, declmode_t Mode)
} else { } else {
if (Mode == DM_NEED_IDENT) { if (Mode == DM_NEED_IDENT) {
/* Some fix point tokens that are used for error recovery */ /* Some fix point tokens that are used for error recovery */
static const token_t TokenList[] = { TOK_COMMA, TOK_SEMI }; static const token_t TokenList[] = { TOK_COMMA, TOK_SEMI, TOK_LCURLY, TOK_RCURLY };
Error ("Identifier expected"); Error ("Identifier expected");
/* Try some smart error recovery */ /* Try some smart error recovery */
SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0])); SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0]));
/* Skip curly braces */
if (CurTok.Tok == TOK_LCURLY) {
static const token_t CurlyToken[] = { TOK_RCURLY };
SkipTokens (CurlyToken, sizeof(CurlyToken) / sizeof(CurlyToken[0]));
NextToken ();
} else if (CurTok.Tok == TOK_RCURLY) {
NextToken ();
}
} }
D->Ident[0] = '\0'; D->Ident[0] = '\0';
} }

View File

@@ -71,8 +71,9 @@ enum typespec_t {
/* Masks for the Flags field in DeclSpec */ /* Masks for the Flags field in DeclSpec */
#define DS_DEF_STORAGE 0x0001U /* Default storage class used */ #define DS_DEF_STORAGE 0x0001U /* Default storage class used */
#define DS_DEF_TYPE 0x0002U /* Default type used */ #define DS_NO_TYPE 0x0002U /* No type explicitly specified */
#define DS_EXTRA_TYPE 0x0004U /* Extra type declared */ #define DS_DEF_TYPE 0x0006U /* Default type used */
#define DS_EXTRA_TYPE 0x0008U /* Extra type declared */
#define DS_NEW_TYPE_DECL 0x0010U /* New type declared */ #define DS_NEW_TYPE_DECL 0x0010U /* New type declared */
#define DS_NEW_TYPE_DEF 0x0020U /* New type defined */ #define DS_NEW_TYPE_DEF 0x0020U /* New type defined */
#define DS_NEW_TYPE (DS_NEW_TYPE_DECL | DS_NEW_TYPE_DEF) #define DS_NEW_TYPE (DS_NEW_TYPE_DECL | DS_NEW_TYPE_DEF)

View File

@@ -1439,7 +1439,7 @@ static void StructRef (ExprDesc* Expr)
/* Skip the token and check for an identifier */ /* Skip the token and check for an identifier */
NextToken (); NextToken ();
if (CurTok.Tok != TOK_IDENT) { if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected"); Error ("Identifier expected for %s member", GetBasicTypeName (Expr->Type));
/* Make the expression an integer at address zero */ /* Make the expression an integer at address zero */
ED_MakeConstAbs (Expr, 0, type_int); ED_MakeConstAbs (Expr, 0, type_int);
return; return;

View File

@@ -1,3 +1,5 @@
bug1889-missing-identifier.c:3: Error: Identifier expected bug1889-missing-identifier.c:3: Error: Identifier expected
bug1889-missing-identifier.c:3: Error: ';' expected
bug1889-missing-identifier.c:3: Warning: Implicit 'int' is an obsolete feature
bug1889-missing-identifier.c:4: Error: Identifier expected bug1889-missing-identifier.c:4: Error: Identifier expected
bug1889-missing-identifier.c:4: Warning: Implicit 'int' is an obsolete feature bug1889-missing-identifier.c:4: Warning: Implicit 'int' is an obsolete feature