scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit f9e48140e72d80782d7962ad7424e3bd5141a008
parent e91b51fe19fc58e4814eed28fda80ed3990078ea
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 26 Oct 2022 15:12:57 +0200

cc1: Improve k&r function semantic

Combination of k&r function with ansi functions is not easy,
and there are two cases that were not handled in the best way:

- A function definition without parameter list is a definition
  of a function with no parameters.
- When function are combined the combinations that produce
  runnable code because the call convention is compatible.

Diffstat:
Msrc/cmd/cc/cc1/decl.c | 30+++++++++++++++++-------------
Msrc/cmd/cc/cc1/types.c | 77++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 85 insertions(+), 22 deletions(-)

diff --git a/src/cmd/cc/cc1/decl.c b/src/cmd/cc/cc1/decl.c @@ -187,21 +187,15 @@ redcl(Symbol *sym, Type *tp, int sclass) int flags; char *name = sym->name; - if (sym->type->op == FTN && tp->op == FTN) { - Type *ntp = sym->type; - if (eqtype(ntp->type, tp->type, 1)) { - if (tp->prop & TK_R) - tp = ntp; - if (sym->type->prop & TK_R) - sym->type = tp; - } - } - if (!eqtype(sym->type, tp, 1)) { errorp("conflicting types for '%s'", name); return sym; } + /* we prefere ansi types over k&r types */ + if ((sym->type->prop & TK_R) == 0 && (tp->prop & TK_R) != 0) + sym->type = tp; + if (sym->token == TYPEIDEN && sclass != TYPEDEF || sym->token != TYPEIDEN && sclass == TYPEDEF) { goto redeclaration; @@ -416,7 +410,6 @@ krfun(struct declarators *dp) { int toomany = 0; - if (yytoken != ')') toomany = krpars(dp); @@ -511,10 +504,10 @@ funbody(Symbol *sym, Symbol *pars[]) if (!sym) return 0; + tp = sym->type; if (tp->op != FTN) return 0; - if (!isfunbody(yytoken) || sym->ns != NS_IDEN) { emit(ODECL, sym); endfundcl(tp, pars); @@ -533,7 +526,7 @@ funbody(Symbol *sym, Symbol *pars[]) tp->prop |= TFUNDEF; curfun = sym; - if (sym->type->prop & TK_R) { + if (tp->prop & TK_R) { while (yytoken != '{') { dodcl(REP, parameter, NS_IDEN, sym->type); expect(';'); @@ -562,6 +555,17 @@ funbody(Symbol *sym, Symbol *pars[]) popctx(); flushtypes(); curfun = NULL; + + /* + * A function declaration without arguments is a k&r function, + * but when it is a definition is a function with 0 arguments + */ + if ((tp->prop & TK_R) && *pars == NULL) { + tp = mktype(tp->type, FTN, 0, NULL); + tp->prop |= TFUNDEF; + sym->type = tp; + } + return 1; } diff --git a/src/cmd/cc/cc1/types.c b/src/cmd/cc/cc1/types.c @@ -353,11 +353,77 @@ mktype(Type *tp, int op, TINT nelem, Type *pars[]) return bp; } +/* + * If one type has a parameter type list and the other type is specified by + * a function declarator that is not part of a function definition and that + * contains an empty identifier list, the parameter list shall not have an + * ellipsis terminator and the type of each parameter shall be compatible + * with the type that results from the application of the default argument + * promotions. + */ +static int +eqfuns(Type *tp1, Type *tp2, int equiv) +{ + TINT n; + int f1kr, f2kr; + Type *krf, *ansi, **pp, *p; + + f1kr = (tp1->prop&TK_R) != 0; + f2kr = (tp2->prop&TK_R) != 0; + + /* 1: 2 ansi functions */ + if (!f1kr && !f2kr) { + Type **p1, **p2; + if (tp1->n.elem != tp2->n.elem) + return 0; + p1 = tp1->p.pars, p2 = tp2->p.pars; + for (n = tp1->n.elem; n > 0; --n) { + if (!eqtype(*p1++, *p2++, equiv)) + return 0; + } + goto check_base; + } + + /* 2: 2 k&r functions */ + if (f1kr && f2kr) + goto check_base; + + /* 3: 1 k&r function + 1 ansi function */ + if (!equiv) + return 0; + + if (f1kr) { + krf = tp1; + ansi = tp2; + } else { + ansi = tp1; + krf = tp2; + } + + for (pp = ansi->p.pars; p = *pp; ++pp) { + switch (p->op) { + case ELLIPSIS: + return 0; + case INT: + case ENUM: + if (p->n.rank < inttype->n.rank) + return 0; + break; + case FLOAT: + if (p == floattype) + return 0; + break; + } + } + +check_base: + return eqtype(tp1->type, tp2->type, equiv); +} + int eqtype(Type *tp1, Type *tp2, int equiv) { TINT n; - Type **p1, **p2; Symbol **s1, **s2; if (tp1 == tp2) @@ -385,14 +451,7 @@ eqtype(Type *tp1, Type *tp2, int equiv) } return 1; case FTN: - if (tp1->n.elem != tp2->n.elem) - return 0; - p1 = tp1->p.pars, p2 = tp2->p.pars; - for (n = tp1->n.elem; n > 0; --n) { - if (!eqtype(*p1++, *p2++, equiv)) - return 0; - } - goto check_base; + return eqfuns(tp1, tp2, equiv); case ARY: if (equiv && (tp1->n.elem == 0 || tp2->n.elem == 0)) goto check_base;