mirror of
https://github.com/cc65/cc65.git
synced 2024-12-28 06:30:16 +00:00
Fixed missing diagnosis on function parameter lists with trailing commas.
This commit is contained in:
parent
bc97bce8c1
commit
f8fe1d1560
@ -1740,10 +1740,12 @@ 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 */
|
||||||
{
|
{
|
||||||
unsigned PrevErrorCount = ErrorCount;
|
if (CurTok.Tok == TOK_RPAREN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse params */
|
/* Parse params */
|
||||||
while (CurTok.Tok != TOK_RPAREN) {
|
while (1) {
|
||||||
|
|
||||||
/* List of identifiers expected */
|
/* List of identifiers expected */
|
||||||
if (CurTok.Tok == TOK_IDENT) {
|
if (CurTok.Tok == TOK_IDENT) {
|
||||||
@ -1768,29 +1770,33 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for more parameters */
|
/* Check for more parameters */
|
||||||
if (CurTok.Tok == TOK_COMMA) {
|
if (CurTok.Tok != TOK_COMMA) {
|
||||||
NextToken ();
|
|
||||||
} else {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
NextToken ();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip right paren. We must explicitly check for one here, since some of
|
|
||||||
** the breaks above bail out without checking.
|
|
||||||
*/
|
static void ParseOldStyleParamDeclList (FuncDesc* F attribute ((unused)))
|
||||||
ConsumeRParen ();
|
/* Parse an old-style (K&R) function declarator declaration list */
|
||||||
|
{
|
||||||
|
if (CurTok.Tok == TOK_SEMI) {
|
||||||
|
/* No parameter declaration list */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* An optional list of type specifications follows */
|
/* An optional list of type specifications follows */
|
||||||
while (CurTok.Tok != TOK_LCURLY) {
|
while (CurTok.Tok != TOK_LCURLY) {
|
||||||
|
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
|
int NeedClean;
|
||||||
|
|
||||||
/* Read the declaration specifier */
|
/* Read the declaration specifier */
|
||||||
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
|
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
|
||||||
|
|
||||||
/* Paremeters must have identifiers as names */
|
|
||||||
Spec.Flags |= DS_NO_EMPTY_DECL;
|
|
||||||
|
|
||||||
/* We accept only auto and register as storage class specifiers, but
|
/* We accept only auto and register as storage class specifiers, but
|
||||||
** we ignore all this, since we use auto anyway.
|
** we ignore all this, since we use auto anyway.
|
||||||
*/
|
*/
|
||||||
@ -1799,10 +1805,14 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
Error ("Illegal storage class");
|
Error ("Illegal storage class");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Type must be specified */
|
/* If we haven't got a type specifier yet, something must be wrong */
|
||||||
if ((Spec.Flags & DS_TYPE_MASK) == DS_NONE) {
|
if ((Spec.Flags & DS_TYPE_MASK) == DS_NONE) {
|
||||||
Error ("Expected declaration specifiers");
|
/* Avoid extra errors if it was a failed type specifier */
|
||||||
break;
|
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 */
|
||||||
@ -1811,7 +1821,12 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
Declarator Decl;
|
Declarator Decl;
|
||||||
|
|
||||||
/* Read the parameter */
|
/* Read the parameter */
|
||||||
ParseDecl (&Spec, &Decl, DM_IDENT_OR_EMPTY);
|
NeedClean = ParseDecl (&Spec, &Decl, DM_IDENT_OR_EMPTY);
|
||||||
|
|
||||||
|
/* Bail out if there are errors */
|
||||||
|
if (NeedClean <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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) {
|
||||||
@ -1820,9 +1835,9 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Decl.Ident[0] != '\0') {
|
if (Decl.Ident[0] != '\0') {
|
||||||
|
|
||||||
/* We have a name given. Search for the symbol */
|
/* We have a name given. Search for the symbol */
|
||||||
SymEntry* Param = FindLocalSym (Decl.Ident);
|
SymEntry* Param = FindLocalSym (Decl.Ident);
|
||||||
|
|
||||||
if (Param) {
|
if (Param) {
|
||||||
/* Check if we already changed the type for this
|
/* Check if we already changed the type for this
|
||||||
** parameter.
|
** parameter.
|
||||||
@ -1837,35 +1852,54 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
Error ("Redefinition for parameter '%s'", Param->Name);
|
Error ("Redefinition for parameter '%s'", Param->Name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Error ("Unknown identifier: '%s'", Decl.Ident);
|
Error ("Unknown parameter '%s'", Decl.Ident);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurTok.Tok == TOK_COMMA) {
|
/* Initialization is not allowed */
|
||||||
NextToken ();
|
if (CurTok.Tok == TOK_ASSIGN) {
|
||||||
} else {
|
Error ("Parameter '%s' cannot be initialized", Decl.Ident);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Variable list must be semicolon terminated */
|
|
||||||
ConsumeSemi ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PrevErrorCount != ErrorCount && CurTok.Tok != TOK_LCURLY) {
|
|
||||||
/* Try some smart error recovery */
|
/* Try some smart error recovery */
|
||||||
SmartErrorSkip (0);
|
SmartErrorSkip (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for more declarators */
|
||||||
|
if (CurTok.Tok != TOK_COMMA) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NextToken ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EndOfDecl:
|
||||||
|
if (NeedClean > 0) {
|
||||||
|
/* Must be followed by a semicolon */
|
||||||
|
if (ConsumeSemi ()) {
|
||||||
|
NeedClean = 0;
|
||||||
|
} else {
|
||||||
|
NeedClean = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try some smart error recovery */
|
||||||
|
if (NeedClean < 0) {
|
||||||
|
SmartErrorSkip (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ParseAnsiParamList (FuncDesc* F)
|
static void ParseAnsiParamList (FuncDesc* F)
|
||||||
/* Parse a new-style (ANSI) parameter list */
|
/* Parse a new-style (ANSI) parameter list */
|
||||||
{
|
{
|
||||||
|
if (CurTok.Tok == TOK_RPAREN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse params */
|
/* Parse params */
|
||||||
while (CurTok.Tok != TOK_RPAREN) {
|
while (1) {
|
||||||
|
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
Declarator Decl;
|
Declarator Decl;
|
||||||
@ -1894,7 +1928,7 @@ static void ParseAnsiParamList (FuncDesc* F)
|
|||||||
|
|
||||||
/* Type must be specified */
|
/* Type must be specified */
|
||||||
if ((Spec.Flags & DS_TYPE_MASK) == DS_NONE) {
|
if ((Spec.Flags & DS_TYPE_MASK) == DS_NONE) {
|
||||||
Error ("Type specifier missing");
|
Error ("Declaration specifier or '...' expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Warn about new local type declaration */
|
/* Warn about new local type declaration */
|
||||||
@ -1945,18 +1979,12 @@ static void ParseAnsiParamList (FuncDesc* F)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for more parameters */
|
/* Check for end of parameter type list */
|
||||||
if (CurTok.Tok == TOK_COMMA) {
|
if (CurTok.Tok != TOK_COMMA) {
|
||||||
NextToken ();
|
|
||||||
} else {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
NextToken ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip right paren. We must explicitly check for one here, since some of
|
|
||||||
** the breaks above bail out without checking.
|
|
||||||
*/
|
|
||||||
ConsumeRParen ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1998,9 +2026,12 @@ static FuncDesc* ParseFuncDecl (void)
|
|||||||
if ((F->Flags & FD_OLDSTYLE) == 0) {
|
if ((F->Flags & FD_OLDSTYLE) == 0) {
|
||||||
/* New-style function */
|
/* New-style function */
|
||||||
ParseAnsiParamList (F);
|
ParseAnsiParamList (F);
|
||||||
|
ConsumeRParen ();
|
||||||
} else {
|
} else {
|
||||||
/* Old-style function */
|
/* Old-style function */
|
||||||
ParseOldStyleParamList (F);
|
ParseOldStyleParamList (F);
|
||||||
|
ConsumeRParen ();
|
||||||
|
ParseOldStyleParamDeclList (F);
|
||||||
}
|
}
|
||||||
PopLexicalLevel ();
|
PopLexicalLevel ();
|
||||||
|
|
||||||
|
3
test/err/bug2301-trailing-coma-1.c
Normal file
3
test/err/bug2301-trailing-coma-1.c
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/* Bug #2301 - Function parameter list with an extra trailing comma should not compile */
|
||||||
|
|
||||||
|
int foo(int a,); /* Should fail */
|
6
test/err/bug2301-trailing-coma-2.c
Normal file
6
test/err/bug2301-trailing-coma-2.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/* Bug #2301 - Function parameter list with an extra trailing comma should not compile */
|
||||||
|
|
||||||
|
int bar(a,) int a; /* Should fail */
|
||||||
|
{
|
||||||
|
return a;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user