1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-28 03:29:39 +00:00

More accurate diagnostic messages on wrong missing declaration specifiers.

This commit is contained in:
acqn 2023-12-10 15:46:48 +08:00
parent cadf8012f6
commit 3215d377ea
3 changed files with 70 additions and 10 deletions

View File

@ -88,6 +88,7 @@ static void Parse (void)
/* Fill up the next token with a bogus semicolon and start the tokenizer */ /* Fill up the next token with a bogus semicolon and start the tokenizer */
NextTok.Tok = TOK_SEMI; NextTok.Tok = TOK_SEMI;
NextToken (); NextToken ();
NextToken ();
/* Parse until end of input */ /* Parse until end of input */
while (CurTok.Tok != TOK_CEOF) { while (CurTok.Tok != TOK_CEOF) {
@ -98,6 +99,7 @@ static void Parse (void)
/* Check for empty statements */ /* Check for empty statements */
if (CurTok.Tok == TOK_SEMI) { if (CurTok.Tok == TOK_SEMI) {
/* TODO: warn on this if we have a pedantic mode */
NextToken (); NextToken ();
continue; continue;
} }
@ -137,6 +139,16 @@ static void Parse (void)
continue; continue;
} }
/* If we haven't got a type specifier yet, something must be wrong */
if ((Spec.Flags & DS_TYPE_MASK) == DS_NONE) {
/* Avoid extra errors if it was a failed type specifier */
if ((Spec.Flags & DS_EXTRA_TYPE) == 0) {
Error ("Declaration specifier expected");
}
NeedClean = -1;
goto EndOfDecl;
}
/* Read declarations for this type */ /* Read declarations for this type */
Comma = 0; Comma = 0;
while (1) { while (1) {
@ -355,6 +367,7 @@ static void Parse (void)
} }
} }
EndOfDecl:
/* Try some smart error recovery */ /* Try some smart error recovery */
if (NeedClean < 0) { if (NeedClean < 0) {
SmartErrorSkip (1); SmartErrorSkip (1);

View File

@ -979,6 +979,13 @@ static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags)
DeclSpec Spec; DeclSpec Spec;
int NeedClean = 0; int NeedClean = 0;
/* Check for extra semicolons */
if (CurTok.Tok == TOK_SEMI) {
/* TODO: warn on this if we have a pedantic mode */
NextToken ();
continue;
}
/* Check for a _Static_assert */ /* Check for a _Static_assert */
if (CurTok.Tok == TOK_STATIC_ASSERT) { if (CurTok.Tok == TOK_STATIC_ASSERT) {
ParseStaticAssert (); ParseStaticAssert ();
@ -995,6 +1002,16 @@ static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags)
continue; continue;
} }
/* If we haven't got a type specifier yet, something must be wrong */
if ((Spec.Flags & DS_TYPE_MASK) == DS_NONE) {
/* Avoid extra errors if it was a failed type specifier */
if ((Spec.Flags & DS_EXTRA_TYPE) == 0) {
Error ("Declaration specifier expected");
}
NeedClean = -1;
goto EndOfDecl;
}
/* Allow anonymous bit-fields */ /* Allow anonymous bit-fields */
Spec.Flags |= DS_ALLOW_BITFIELD; Spec.Flags |= DS_ALLOW_BITFIELD;
@ -1107,6 +1124,7 @@ NextMember:
NextToken (); NextToken ();
} }
EndOfDecl:
if (NeedClean > 0) { if (NeedClean > 0) {
/* Must be followed by a semicolon */ /* Must be followed by a semicolon */
if (ConsumeSemi ()) { if (ConsumeSemi ()) {
@ -1181,6 +1199,13 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags)
DeclSpec Spec; DeclSpec Spec;
int NeedClean = 0; int NeedClean = 0;
/* Check for extra semicolons */
if (CurTok.Tok == TOK_SEMI) {
/* TODO: warn on this if we have a pedantic mode */
NextToken ();
continue;
}
/* Check for a _Static_assert */ /* Check for a _Static_assert */
if (CurTok.Tok == TOK_STATIC_ASSERT) { if (CurTok.Tok == TOK_STATIC_ASSERT) {
ParseStaticAssert (); ParseStaticAssert ();
@ -1197,6 +1222,16 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags)
continue; continue;
} }
/* If we haven't got a type specifier yet, something must be wrong */
if ((Spec.Flags & DS_TYPE_MASK) == DS_NONE) {
/* Avoid extra errors if it was a failed type specifier */
if ((Spec.Flags & DS_EXTRA_TYPE) == 0) {
Error ("Declaration specifier expected");
}
NeedClean = -1;
goto EndOfDecl;
}
/* Allow anonymous bit-fields */ /* Allow anonymous bit-fields */
Spec.Flags |= DS_ALLOW_BITFIELD; Spec.Flags |= DS_ALLOW_BITFIELD;
@ -1362,6 +1397,7 @@ NextMember:
NextToken (); NextToken ();
} }
EndOfDecl:
if (NeedClean > 0) { if (NeedClean > 0) {
/* Must be followed by a semicolon */ /* Must be followed by a semicolon */
if (ConsumeSemi ()) { if (ConsumeSemi ()) {
@ -1559,6 +1595,8 @@ static void ParseTypeSpec (DeclSpec* Spec, typespec_t TSFlags)
case TOK_UNION: case TOK_UNION:
NextToken (); NextToken ();
/* Remember we have an extra type decl */
Spec->Flags |= DS_EXTRA_TYPE;
/* Check for tag name */ /* Check for tag name */
if (CurTok.Tok == TOK_IDENT) { if (CurTok.Tok == TOK_IDENT) {
strcpy (Ident, CurTok.Ident); strcpy (Ident, CurTok.Ident);
@ -1570,8 +1608,6 @@ static void ParseTypeSpec (DeclSpec* Spec, typespec_t TSFlags)
UseDefaultType (Spec, TS_DEFAULT_TYPE_NONE); UseDefaultType (Spec, TS_DEFAULT_TYPE_NONE);
break; break;
} }
/* Remember we have an extra type decl */
Spec->Flags |= DS_EXTRA_TYPE;
/* Declare the union in the current scope */ /* Declare the union in the current scope */
TagEntry = ParseUnionSpec (Ident, &Spec->Flags); TagEntry = ParseUnionSpec (Ident, &Spec->Flags);
/* Encode the union entry into the type */ /* Encode the union entry into the type */
@ -1582,6 +1618,8 @@ static void ParseTypeSpec (DeclSpec* Spec, typespec_t TSFlags)
case TOK_STRUCT: case TOK_STRUCT:
NextToken (); NextToken ();
/* Remember we have an extra type decl */
Spec->Flags |= DS_EXTRA_TYPE;
/* Check for tag name */ /* Check for tag name */
if (CurTok.Tok == TOK_IDENT) { if (CurTok.Tok == TOK_IDENT) {
strcpy (Ident, CurTok.Ident); strcpy (Ident, CurTok.Ident);
@ -1593,8 +1631,6 @@ static void ParseTypeSpec (DeclSpec* Spec, typespec_t TSFlags)
UseDefaultType (Spec, TS_DEFAULT_TYPE_NONE); UseDefaultType (Spec, TS_DEFAULT_TYPE_NONE);
break; break;
} }
/* Remember we have an extra type decl */
Spec->Flags |= DS_EXTRA_TYPE;
/* Declare the struct in the current scope */ /* Declare the struct in the current scope */
TagEntry = ParseStructSpec (Ident, &Spec->Flags); TagEntry = ParseStructSpec (Ident, &Spec->Flags);
/* Encode the struct entry into the type */ /* Encode the struct entry into the type */
@ -1605,6 +1641,8 @@ static void ParseTypeSpec (DeclSpec* Spec, typespec_t TSFlags)
case TOK_ENUM: case TOK_ENUM:
NextToken (); NextToken ();
/* Remember we have an extra type decl */
Spec->Flags |= DS_EXTRA_TYPE;
/* Check for tag name */ /* Check for tag name */
if (CurTok.Tok == TOK_IDENT) { if (CurTok.Tok == TOK_IDENT) {
strcpy (Ident, CurTok.Ident); strcpy (Ident, CurTok.Ident);
@ -1616,8 +1654,6 @@ static void ParseTypeSpec (DeclSpec* Spec, typespec_t TSFlags)
UseDefaultType (Spec, TS_DEFAULT_TYPE_NONE); UseDefaultType (Spec, TS_DEFAULT_TYPE_NONE);
break; break;
} }
/* Remember we have an extra type decl */
Spec->Flags |= DS_EXTRA_TYPE;
/* Parse the enum decl */ /* Parse the enum decl */
TagEntry = ParseEnumSpec (Ident, &Spec->Flags); TagEntry = ParseEnumSpec (Ident, &Spec->Flags);
/* Encode the enum entry into the type */ /* Encode the enum entry into the type */
@ -1658,9 +1694,7 @@ static void ParseTypeSpec (DeclSpec* Spec, typespec_t TSFlags)
** in DeclareLocals. The type code used here doesn't matter as ** in DeclareLocals. The type code used here doesn't matter as
** long as it has no qualifiers. ** long as it has no qualifiers.
*/ */
Spec->Flags |= DS_DEF_TYPE; UseDefaultType (Spec, TS_DEFAULT_TYPE_INT);
Spec->Type[0].C = T_INT;
Spec->Type[1].C = T_END;
break; break;
} }
/* FALL THROUGH */ /* FALL THROUGH */
@ -2376,7 +2410,9 @@ void CheckEmptyDecl (const DeclSpec* Spec)
** warning if not. ** warning if not.
*/ */
{ {
if ((Spec->Flags & DS_EXTRA_TYPE) == 0) { if ((Spec->Flags & DS_TYPE_MASK) == DS_NONE) {
/* No declaration at all */
} else if ((Spec->Flags & DS_EXTRA_TYPE) == 0) {
Warning ("Declaration does not declare anything"); Warning ("Declaration does not declare anything");
} else if (IsClassStruct (Spec->Type) && } else if (IsClassStruct (Spec->Type) &&
!IsIncompleteESUType (Spec->Type) && !IsIncompleteESUType (Spec->Type) &&

View File

@ -588,6 +588,16 @@ void DeclareLocals (void)
continue; continue;
} }
/* If we haven't got a type specifier yet, something must be wrong */
if ((Spec.Flags & DS_TYPE_MASK) == DS_NONE) {
/* Avoid extra errors if it was a failed type specifier */
if ((Spec.Flags & DS_EXTRA_TYPE) == 0) {
Error ("Declaration specifier expected");
}
NeedClean = -1;
goto EndOfDecl;
}
/* Parse a comma separated variable list */ /* Parse a comma separated variable list */
while (1) { while (1) {
@ -616,6 +626,7 @@ void DeclareLocals (void)
} }
} }
EndOfDecl:
/* Try some smart error recovery */ /* Try some smart error recovery */
if (NeedClean < 0) { if (NeedClean < 0) {
SmartErrorSkip (1); SmartErrorSkip (1);