[hackers] [scc] [cc1] Fix function prototype declaration || Roberto E. Vargas Caballero
commit 14eceba2511c69bd9806d0085595d386ef7a58eb
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
AuthorDate: Mon Mar 6 08:10:57 2017 +0100
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
CommitDate: Mon Mar 6 13:00:58 2017 +0100
[cc1] Fix function prototype declaration
The emission of prototypes were done in decl() after returning from
dodcl, and in that moment it was when popctx() was called. This was
totally wrong because it fails with something like:
int f(int a), a;
diff --git a/cc1/cc1.h b/cc1/cc1.h
index 1ae5724..77d60a6 100644
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
_AT_@ -3,6 +3,7 @@
#define INPUTSIZ LINESIZ
#define GLOBALCTX 0
+#define PARAMCTX 1
#define NR_USWITCHES 20
_AT_@ -22,6 +23,7 @@ enum typeprops {
TAGGREG = 1 << 4, /* the type is struct or union */
TK_R = 1 << 5, /* this is a K&R-function */
TELLIPSIS= 1 << 6, /* this function has an ellipsis par */
+ TFUNDEF = 2 << 7, /* function definition */
};
enum inputtype {
diff --git a/cc1/decl.c b/cc1/decl.c
index ebb4e2c..f020484 100644
--- a/cc1/decl.c
+++ b/cc1/decl.c
_AT_@ -13,21 +13,22 @@ static char sccsid[] = "@(#) ./cc1/decl.c";
#define NOREP 0
#define REP 1
+#define QUIET 1
+#define NOQUIET 0
#define NR_DCL_TYP (NR_DECLARATORS+NR_FUNPARAM)
-#define NR_DCL_ARG (NR_DECLARATORS+NR_FUNPARAM+1)
struct declarators {
unsigned nr;
unsigned ns;
- unsigned nr_types, nr_pars;
- Symbol **pars;
+ struct decl *dcl;
+ unsigned nr_types;
Type **tpars;
+ Symbol **pars;
struct declarator {
unsigned char op;
TINT nelem;
Symbol *sym;
- Symbol **pars;
Type **tpars;
} d [NR_DECLARATORS];
};
_AT_@ -37,14 +38,25 @@ struct decl {
int sclass;
int qualifier;
Symbol *sym;
- Symbol **pars;
Type *type;
Type *parent;
- Symbol *bufpars[NR_DCL_ARG];
- Type *buftpars[NR_DCL_ARG];
+ Type *buftpars[NR_DCL_TYP];
};
static void
+endfundcl(Type *tp, Symbol **pars)
+{
+ if (tp->prop&TK_R && *pars)
+ warn("parameter names (without types) in function declaration");
+ /*
+ * avoid non used warnings in prototypes
+ */
+ while (*pars)
+ (*pars++)->flags |= SUSED;
+ popctx();
+}
+
+static void
push(struct declarators *dp, int op, ...)
{
va_list va;
_AT_@ -67,7 +79,6 @@ push(struct declarators *dp, int op, ...)
case FTN:
p->nelem = va_arg(va, unsigned);
p->tpars = va_arg(va, Type **);
- p->pars = va_arg(va, Symbol **);
break;
case IDEN:
p->sym = va_arg(va, Symbol *);
_AT_@ -80,6 +91,7 @@ static int
pop(struct declarators *dp, struct decl *dcl)
{
struct declarator *p;
+ Symbol **bp;
if (dp->nr == 0)
return 0;
_AT_@ -89,17 +101,10 @@ pop(struct declarators *dp, struct decl *dcl)
dcl->sym = p->sym;
return 1;
}
- if (dcl->type->op == FTN) {
- /*
- * constructor applied to a
- * function. We don't need
- * the parameter symbols anymore.
- */
- popctx();
- dcl->pars = NULL;
- }
- if (p->op == FTN || p->op == KRFTN)
- dcl->pars = p->pars;
+
+ if (dcl->type->op == FTN)
+ endfundcl(dcl->type, dp->pars);
+
dcl->type = mktype(dcl->type, p->op, p->nelem, p->tpars);
return 1;
}
_AT_@ -280,7 +285,7 @@ identifier(struct decl *dcl)
initializer(sym, sym->type);
if (!(sym->flags & (SGLOBAL|SEXTERN)) && tp->op != FTN)
sym->flags |= SDEFINED;
- if (sym->token == IDEN && sym->type->op != FTN)
+ if (sym->token == IDEN && tp->op != FTN)
emit(ODECL, sym);
return sym;
}
_AT_@ -346,53 +351,73 @@ static Symbol *dodcl(int rep,
unsigned ns,
Type *type);
-static unsigned
-krfun(struct declarators *dp)
+static int
+krargs(Symbol *pars[], unsigned *nparsp)
{
Symbol *sym;
- unsigned toomany = 0, npars = 0;
+ int toomany = 0;
+ unsigned npars = 0;
- if (yytoken != ')') {
- do {
- sym = yylval.sym;
- expect(IDEN);
- sym->type = inttype;
- sym->flags |= SAUTO;
- if ((sym = install(NS_IDEN, sym)) == NULL) {
- errorp("redefinition of parameter '%s'",
- yylval.sym->name);
- continue;
- }
- if (dp->nr_pars < NR_DCL_ARG-1) {
- ++npars;
- ++dp->nr_pars;
- *dp->pars++ = sym;
- continue;
- }
- if (!toomany)
- errorp("too many parameters in function definition");
- toomany = 1;
- } while (accept(','));
- }
+ do {
+ sym = yylval.sym;
+ expect(IDEN);
+ sym->type = inttype;
+ sym->flags |= SAUTO;
+ if ((sym = install(NS_IDEN, sym)) == NULL) {
+ errorp("redefinition of parameter '%s'",
+ yylval.sym->name);
+ continue;
+ }
+ if (npars < NR_FUNARG) {
+ ++npars;
+ *pars++ = sym;
+ continue;
+ }
+ if (!toomany)
+ toomany = 1;
+ } while (accept(','));
- if (dp->nr_types < NR_DCL_TYP) {
+ *nparsp = npars;
+ return toomany;
+}
+
+static void
+krfun(struct declarators *dp,
+ Symbol *pars[], unsigned *ntypep, unsigned *nparsp)
+{
+ Symbol *sym;
+ int toomany = 0;
+
+
+ if (yytoken != ')')
+ toomany = krargs(pars, nparsp);
+ else
+ *nparsp = 0;
+
+ *ntypep = 1;
+ if (dp->nr_types == NR_DCL_TYP) {
+ toomany = 1;
+ } else {
++dp->nr_types;
*dp->tpars++ = ellipsistype;
}
- return 1;
+ if (toomany)
+ errorp("too many parameters in function definition");
}
-static unsigned
-ansifun(struct declarators *dp)
+static void
+ansifun(struct declarators *dp,
+ Symbol *pars[], unsigned *ntypep, unsigned *nparsp)
{
Symbol *sym;
- unsigned ntype, toomany, distoomany, voidpar;
+ unsigned npars, ntype, toomany, distoomany, voidpar;
Type type, *tp;
type.n.elem = 0;
type.prop = 0;
- ntype = toomany = toomany = distoomany = voidpar = 0;
+ npars = ntype = toomany = distoomany = voidpar = 0;
+
do {
if (accept(ELLIPSIS)) {
if (ntype < 1)
_AT_@ -411,11 +436,11 @@ ansifun(struct declarators *dp)
}
if (sym) {
- if (dp->nr_pars == NR_DCL_ARG-1) {
+ if (npars == NR_FUNARG) {
toomany = 1;
} else {
- dp->nr_pars++;
- *dp->pars++ = sym;
+ npars++;
+ *pars++ = sym;
}
}
_AT_@ -429,29 +454,79 @@ ansifun(struct declarators *dp)
}
}
- if (toomany == 1 && !distoomany) {
- errorp("too many parameters in function definition");
- distoomany = 1;
- }
} while (accept(','));
+ if (toomany == 1)
+ errorp("too many parameters in function definition");
if (voidpar && ntype > 1)
errorp("'void' must be the only parameter");
+ *ntypep = ntype;
+ *nparsp = npars;
+}
+
+static int
+funbody(Symbol *sym, Symbol *pars[])
+{
+ Symbol *par;
+ Type *tp;
- return ntype;
+ if (!sym)
+ return 0;
+ tp = sym->type;
+ if (tp->op != FTN)
+ return 0;
+
+ switch (yytoken) {
+ case '{':
+ case TYPE:
+ case TYPEIDEN:
+ if (curctx != PARAMCTX)
+ errorp("nested function declaration");
+ if (sym && sym->ns == NS_IDEN)
+ break;
+ default:
+ emit(ODECL, sym);
+ endfundcl(tp, pars);
+ return 0;
+ }
+
+ tp->prop |= TFUNDEF;
+ curfun = sym;
+ if (sym->type->prop & TK_R) {
+ while (yytoken != '{') {
+ par = dodcl(REP, parameter, NS_IDEN, sym->type);
+ expect(';');
+ }
+ }
+ if (sym->flags & STYPEDEF)
+ errorp("function definition declared 'typedef'");
+ if (sym->flags & SDEFINED)
+ errorp("redefinition of '%s'", sym->name);
+ if (sym->flags & SEXTERN) {
+ sym->flags &= ~SEXTERN;
+ sym->flags |= SGLOBAL;
+ }
+ sym->flags |= SDEFINED;
+ sym->flags &= ~SEMITTED;
+ sym->u.pars = pars;
+ emit(OFUN, sym);
+ compound(NULL, NULL, NULL);
+ emit(OEFUN, NULL);
+ popctx();
+ flushtypes();
+ curfun = NULL;
+ return 1;
}
static void
fundcl(struct declarators *dp)
{
- Symbol **pars = dp->pars;
Type **types = dp->tpars;
- unsigned ntypes, typefun;
- unsigned (*fun)(struct declarators *dp);
+ unsigned npars, ntypes, typefun;
+ void (*fun)(struct declarators *, Symbol **, unsigned *, unsigned *);
pushctx();
expect('(');
-
if (yytoken == ')' || yytoken == IDEN) {
typefun = KRFTN;
fun = krfun;
_AT_@ -459,16 +534,11 @@ fundcl(struct declarators *dp)
typefun = FTN;
fun = ansifun;
}
-
- ntypes = (*fun)(dp);
+ (*fun)(dp, dp->pars, &ntypes, &npars);
+ dp->pars[npars] = NULL;
expect(')');
- if (dp->nr_pars < NR_DCL_ARG) {
- *dp->pars++ = NULL;
- ++dp->nr_pars;
- }
-
- push(dp, typefun, ntypes, types, pars);
+ push(dp, typefun, ntypes, types);
}
static void declarator(struct declarators *dp);
_AT_@ -835,7 +905,7 @@ field(struct decl *dcl)
static Symbol *
dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent)
{
- Symbol *sym;
+ Symbol *sym, *pars[NR_FUNARG+1];
Type *base;
struct decl dcl;
struct declarators stack;
_AT_@ -846,17 +916,19 @@ dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent)
do {
dcl.type = base;
- dcl.pars = NULL;
- stack.nr_pars = stack.nr_types = stack.nr = 0;
- stack.pars = dcl.bufpars;
+ stack.nr_types = stack.nr = 0;
stack.tpars = dcl.buftpars;
+ stack.dcl = &dcl;
stack.ns = ns;
+ stack.pars = pars;
declarator(&stack);
while (pop(&stack, &dcl))
/* nothing */;
sym = (*fun)(&dcl);
+ if (funbody(sym, pars))
+ return sym;
} while (rep && accept(','));
return sym;
_AT_@ -865,60 +937,14 @@ dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent)
void
decl(void)
{
- Symbol **p, *par, *sym, *ocurfun;
+ Symbol *sym;
if (accept(';'))
return;
sym = dodcl(REP, identifier, NS_IDEN, NULL);
-
- if (sym->type->op != FTN) {
- expect(';');
- return;
- }
-
- ocurfun = curfun;
- curfun = sym;
- /*
- * Functions only can appear at global context,
- * but due to parameter context, we have to check
- * against GLOBALCTX+1
- */
- if (curctx != GLOBALCTX+1 || yytoken == ';') {
- emit(ODECL, sym);
- /*
- * avoid non used warnings in prototypes
- */
- for (p = sym->u.pars; p && *p; ++p)
- (*p)->flags |= SUSED;
- popctx();
- curfun = ocurfun;
- expect(';');
+ if (sym->type->prop & TFUNDEF)
return;
- }
- if (sym->type->prop & TK_R) {
- while (yytoken != '{') {
- par = dodcl(REP, parameter, NS_IDEN, sym->type);
- expect(';');
- }
- }
-
- if (sym->flags & STYPEDEF)
- errorp("function definition declared 'typedef'");
- if (sym->flags & SDEFINED)
- errorp("redefinition of '%s'", sym->name);
- if (sym->flags & SEXTERN) {
- sym->flags &= ~SEXTERN;
- sym->flags |= SGLOBAL;
- }
-
- sym->flags |= SDEFINED;
- sym->flags &= ~SEMITTED;
- emit(OFUN, sym);
- compound(NULL, NULL, NULL);
- popctx();
- emit(OEFUN, NULL);
- flushtypes();
- curfun = ocurfun;
+ expect(';');
}
static void
diff --git a/cc1/symbol.c b/cc1/symbol.c
index 97a34d8..686cce4 100644
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
_AT_@ -177,11 +177,6 @@ popctx(void)
killsym(sym);
}
labels = NULL;
-
- if (curfun) {
- free(curfun->u.pars);
- curfun->u.pars = NULL;
- }
}
if (dangling) {
diff --git a/tests/execute/scc-tests.lst b/tests/execute/scc-tests.lst
index 9eafc5d..eda9f33 100644
--- a/tests/execute/scc-tests.lst
+++ b/tests/execute/scc-tests.lst
_AT_@ -115,3 +115,4 @@
0122-localinit.c TODO
0123-doubleconst.c TODO
0124-enumstruct.c TODO
+0125-fundcl.c
Received on Mon Mar 06 2017 - 13:01:09 CET
This archive was generated by hypermail 2.3.0
: Mon Mar 06 2017 - 13:12:19 CET