commit ff5758a151b905af1f39827d8b755c7fccd11961
parent 0bf03263b1eb578bb353c6bc93f1636caaba89d0
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Fri, 21 Aug 2015 00:10:04 +0200
Add basic error recovery in identifier()
The idea is very simple: Don't raise error recovery when you
only have semantic errors, when it is not needed a character
synchronization
Diffstat:
M | cc1/decl.c | | | 81 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ |
1 file changed, 44 insertions(+), 37 deletions(-)
diff --git a/cc1/decl.c b/cc1/decl.c
@@ -128,7 +128,8 @@ parameter(struct decl *dcl)
case STATIC:
case EXTERN:
case AUTO:
- error("bad storage class in function parameter");
+ errorp("bad storage class in function parameter");
+ break;
case REGISTER:
sym->flags |= ISREGISTER;
break;
@@ -266,7 +267,7 @@ specifier(int *sclass)
break;
case TQUALIFIER:
if (qlf && qlf != RESTRICT)
- goto invalid_type;
+ errorp("invalid type specification");
qlf |= yylval.token;
next();
continue;
@@ -314,11 +315,11 @@ specifier(int *sclass)
goto return_type;
}
if (*p)
- goto invalid_type;
+ errorp("invalid type specification");
*p = yylval.token;
if (dcl) {
if (size || sign)
- goto invalid_type;
+ errorp("invalid type specification");
tp = (*dcl)();
goto return_type;
} else {
@@ -341,9 +342,6 @@ return_type:
}
}
return tp;
-
-invalid_type:
- error("invalid type specification");
}
/* TODO: check correctness of the initializator */
@@ -514,6 +512,14 @@ field(struct decl *dcl)
return sym;
}
+static void
+bad_storage(Type *tp, char *name)
+{
+ if (tp->op != FTN)
+ errorp("incorrect storage class for file-scope declaration");
+ errorp("invalid storage class for function '%s'", name);
+}
+
static Symbol *
identifier(struct decl *dcl)
{
@@ -557,7 +563,6 @@ identifier(struct decl *dcl)
if (sym == NULL) {
sym = dcl->sym;
- flags = sym->flags;
if (!eqtype(sym->type, tp))
error("conflicting types for '%s'", name);
if (sym->token == TYPEIDEN && sclass != TYPEDEF ||
@@ -568,32 +573,49 @@ identifier(struct decl *dcl)
if (!(sym->flags & ISEXTERN) || sclass != EXTERN)
goto redeclaration;
} else {
+ sym->u.pars = dcl->pars;
+ flags = sym->flags;
+
switch (sclass) {
case REGISTER:
case AUTO:
- goto bad_storage;
+ bad_storage(tp, name);
+ break;
case NOSCLASS:
- if (flags & ISPRIVATE)
- goto non_after_static;
- flags &= ~ISEXTERN;
- flags |= ISGLOBAL;
+ if ((flags & ISPRIVATE) == 0) {
+ flags &= ~ISEXTERN;
+ flags |= ISGLOBAL;
+ break;
+ }
+ errorp("non-static declaration of '%s' follows static declaration",
+ name);
+ break;
case TYPEDEF:
case EXTERN:
break;
case STATIC:
- if (flags & (ISGLOBAL|ISEXTERN))
- goto static_after_non;
- flags |= ISPRIVATE;
+ if ((flags & (ISGLOBAL|ISEXTERN)) == 0) {
+ flags |= ISPRIVATE;
+ break;
+ }
+ errorp("static declaration of '%s' follows non-static declaration",
+ name);
break;
}
}
+ sym->flags = flags;
} else {
+ sym->type = tp;
+ sym->u.pars = dcl->pars;
flags = sym->flags;
+
switch (sclass) {
case REGISTER:
case AUTO:
- if (curctx == GLOBALCTX || tp->op == FTN)
- goto bad_storage;
+ if (curctx == GLOBALCTX || tp->op == FTN) {
+ bad_storage(tp, name);
+ break;
+ }
flags |= (sclass == REGISTER) ? ISREGISTER : ISAUTO;
break;
case NOSCLASS:
@@ -609,12 +631,9 @@ identifier(struct decl *dcl)
sym->token = TYPEIDEN;
break;
}
+ sym->flags = flags;
}
- sym->u.pars = dcl->pars;
- sym->flags = flags;
- sym->type = tp;
-
if (accept('='))
initializer(sym);
/* TODO: disallow initializators in functions */
@@ -625,21 +644,8 @@ identifier(struct decl *dcl)
return sym;
redeclaration:
- error("redeclaration of '%s'", name);
-
-bad_storage:
- if (tp->op != FTN)
- error("incorrect storage class for file-scope declaration");
-bad_function:
- error("invalid storage class for function '%s'", name);
-
-non_after_static:
- error("non-static declaration of '%s' follows static declaration",
- name);
-
-static_after_non:
- error("static declaration of '%s' follows non-static declaration",
- name);
+ errorp("redeclaration of '%s'", name);
+ return sym;
}
static Symbol *
@@ -714,6 +720,7 @@ decl(void)
prototype:
emit(ODECL, sym);
free(sym->u.pars);
+ sym->u.pars = NULL;
popctx();
}
}