diff options
author | Michael Forney <mforney@mforney.org> | 2024-04-14 23:12:21 -0700 |
---|---|---|
committer | Michael Forney <mforney@mforney.org> | 2024-04-15 01:23:59 -0700 |
commit | cc49fbc44550d3927c592445a3e7f89a4481a63a (patch) | |
tree | 570910b0eb05abac46fe60fba4fbce304ef15a40 | |
parent | 7ee038a55d70ffb94139869acf423ebe0dd52b70 (diff) |
Remove support for non-prototype function declarations and definitions
These were removed in C23.
-rw-r--r-- | cc.h | 2 | ||||
-rw-r--r-- | decl.c | 89 | ||||
-rw-r--r-- | expr.c | 6 | ||||
-rw-r--r-- | qbe.c | 6 | ||||
-rw-r--r-- | test/compatible-function-types.c | 30 | ||||
-rw-r--r-- | test/compatible-function-types.qbe | 16 | ||||
-rw-r--r-- | test/float-promote.c | 10 | ||||
-rw-r--r-- | test/float-promote.qbe | 6 | ||||
-rw-r--r-- | test/kr-function-argument-promotion.c | 10 | ||||
-rw-r--r-- | test/kr-function-argument-promotion.qbe | 18 | ||||
-rw-r--r-- | test/lvalue-conversion.c | 2 | ||||
-rw-r--r-- | type.c | 16 |
12 files changed, 42 insertions, 169 deletions
@@ -215,7 +215,7 @@ struct type { enum typequal ptrqual; } array; struct { - bool isprototype, isvararg, isnoreturn, paraminfo; + bool isvararg, isnoreturn; struct decl *params; size_t nparam; } func; @@ -597,48 +597,27 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs func: t = mktype(TYPEFUNC, 0); t->qual = QUALNONE; - t->u.func.isprototype = false; t->u.func.isvararg = false; t->u.func.isnoreturn = false; t->u.func.params = NULL; t->u.func.nparam = 0; p = &t->u.func.params; - switch (tok.kind) { - case TIDENT: - if (!istypename(s, tok.lit)) { - /* identifier-list (K&R declaration) */ - do { - *p = mkdecl(tok.lit, DECLOBJECT, NULL, QUALNONE, LINKNONE); - p = &(*p)->next; - ++t->u.func.nparam; - next(); - } while (consume(TCOMMA) && tok.kind == TIDENT); + while (tok.kind != TRPAREN) { + *p = parameter(s); + p = &(*p)->next; + ++t->u.func.nparam; + if (!consume(TCOMMA)) + break; + if (consume(TELLIPSIS)) { + t->u.func.isvararg = true; break; } - /* fallthrough */ - default: - t->u.func.isprototype = true; - for (;;) { - *p = parameter(s); - p = &(*p)->next; - ++t->u.func.nparam; - if (!consume(TCOMMA)) - break; - if (consume(TELLIPSIS)) { - t->u.func.isvararg = true; - break; - } - } - if (t->u.func.nparam == 1 && !t->u.func.isvararg && t->u.func.params->type->kind == TYPEVOID && !t->u.func.params->name) { - t->u.func.params = NULL; - t->u.func.nparam = 0; - } - break; - case TRPAREN: - break; + } + if (t->u.func.nparam == 1 && !t->u.func.isvararg && t->u.func.params->type->kind == TYPEVOID && !t->u.func.params->name) { + t->u.func.params = NULL; + t->u.func.nparam = 0; } expect(TRPAREN, "to close function declarator"); - t->u.func.paraminfo = t->u.func.isprototype || t->u.func.params || tok.kind == TLBRACE; listinsert(ptr->prev, &t->link); allowattr = true; break; @@ -741,36 +720,6 @@ parameter(struct scope *s) return mkdecl(name, DECLOBJECT, t.type, t.qual, LINKNONE); } -static bool -paramdecl(struct scope *s, struct decl *params) -{ - struct decl *p; - struct qualtype t, base; - enum storageclass sc; - char *name; - - base = declspecs(s, &sc, NULL, NULL); - if (!base.type) - return false; - if (sc && sc != SCREGISTER) - error(&tok.loc, "parameter declaration has invalid storage-class specifier"); - for (;;) { - t = declarator(s, base, &name, false); - for (p = params; p && strcmp(name, p->name) != 0; p = p->next) - ; - if (!p) - error(&tok.loc, "old-style function declarator has no parameter named '%s'", name); - p->type = typeadjust(t.type, &t.qual); - p->qual = t.qual; - p->u.obj.align = p->type->align; - if (tok.kind == TSEMICOLON) - break; - expect(TCOMMA, "or ';' after parameter declarator"); - } - next(); - return true; -} - static void addmember(struct structbuilder *b, struct qualtype mt, char *name, int align, unsigned long long width) { @@ -1004,7 +953,6 @@ decl(struct scope *s, struct func *f) enum funcspec fs; struct init *init; bool hasinit; - struct decl *p; char *name, *asmname; int allowfunc = !f; struct decl *d, *prior; @@ -1096,19 +1044,6 @@ decl(struct scope *s, struct func *f) t->u.func.isnoreturn |= fs & FUNCNORETURN; if (f && sc && sc != SCEXTERN) /* 6.7.1p7 */ error(&tok.loc, "function '%s' with block scope may only have storage class 'extern'", name); - if (!t->u.func.isprototype && t->u.func.params) { - if (!allowfunc) - error(&tok.loc, "function definition not allowed"); - /* collect type information for parameters before we check compatibility */ - while (paramdecl(s, t->u.func.params)) - ; - if (tok.kind != TLBRACE) - error(&tok.loc, "function declaration with identifier list is not part of definition"); - for (p = t->u.func.params; p; p = p->next) { - if (!p->type) - error(&tok.loc, "old-style function definition does not declare '%s'", p->name); - } - } d = declcommon(s, kind, name, asmname, t, tq, sc, prior); d->u.func.inlinedefn = d->linkage == LINKEXTERN && fs & FUNCINLINE && !(sc & SCEXTERN) && (!prior || prior->u.func.inlinedefn); if (tok.kind == TLBRACE) { @@ -949,10 +949,10 @@ postfixexpr(struct scope *s, struct expr *r) while (tok.kind != TRPAREN) { if (e->u.call.args) expect(TCOMMA, "or ')' after function call argument"); - if (!p && !t->u.func.isvararg && t->u.func.paraminfo) + if (!p && !t->u.func.isvararg) error(&tok.loc, "too many arguments for function call"); *end = assignexpr(s); - if (!t->u.func.isprototype || (t->u.func.isvararg && !p)) + if (t->u.func.isvararg && !p) *end = exprpromote(*end); else *end = exprassign(*end, p->type); @@ -961,7 +961,7 @@ postfixexpr(struct scope *s, struct expr *r) if (p) p = p->next; } - if (p && !t->u.func.isvararg && t->u.func.paraminfo) + if (p && !t->u.func.isvararg) error(&tok.loc, "not enough arguments for function call"); e = decay(e); next(); @@ -473,7 +473,6 @@ mkfunc(struct decl *decl, char *name, struct type *t, struct scope *s) { struct func *f; struct decl *d; - struct type *pt; struct value *v, *pv; f = xmalloc(sizeof(*f)); @@ -488,15 +487,14 @@ mkfunc(struct decl *decl, char *name, struct type *t, struct scope *s) /* allocate space for parameters */ f->paramtemps = xreallocarray(NULL, t->u.func.nparam, sizeof *f->paramtemps); for (d = t->u.func.params, pv = f->paramtemps; d; d = d->next, ++pv) { - pt = t->u.func.isprototype ? d->type : typepromote(d->type, -1); - emittype(pt); + emittype(d->type); functemp(f, pv); if(!d->name) continue; if (d->type->value) { d->value = pv; } else { - v = typecompatible(d->type, pt) ? pv : convert(f, pt, d->type, pv); + v = pv; funcalloc(f, d); funcstore(f, d->type, QUALNONE, (struct lvalue){d->value}, v); } diff --git a/test/compatible-function-types.c b/test/compatible-function-types.c index 4dcd877..1f67cd6 100644 --- a/test/compatible-function-types.c +++ b/test/compatible-function-types.c @@ -1,20 +1,22 @@ void f1(); -void f1(int, void *); +void f1(void); -int f2(); -int f2(double); +void f2(int, char *); +void f2(int, char *); -void f3() {} -void f3(void); +void f3(int(const double)); +void f3(int (*)(double)); -void f4(int, char *); -void f4(int, char *); +void f4(const char *, ...); +void f5(const char[], ...); -void f5(x, y) unsigned x; double y; {} -void f5(unsigned, double); +void f6(const int); +void f6(int); -void f6(const char *, ...); -void f6(const char[], ...); - -void f7(const int); -void f7(int); +static_assert(!__builtin_types_compatible_p(void(), void(int))); +static_assert(!__builtin_types_compatible_p(void(int), void(char))); +static_assert(!__builtin_types_compatible_p(int(float), char(float))); +static_assert(!__builtin_types_compatible_p(void(int, ...), void(int))); +static_assert(!__builtin_types_compatible_p(void(const char *), void(char *))); +static_assert(!__builtin_types_compatible_p(void(char *), void(unsigned char *))); +static_assert(!__builtin_types_compatible_p(void(int, float), void(int, double))); diff --git a/test/compatible-function-types.qbe b/test/compatible-function-types.qbe index 27d9b32..e69de29 100644 --- a/test/compatible-function-types.qbe +++ b/test/compatible-function-types.qbe @@ -1,16 +0,0 @@ -export -function $f3() { -@start.1 -@body.2 - ret -} -export -function $f5(w %.1, d %.3) { -@start.3 - %.2 =l alloc4 4 - storew %.1, %.2 - %.4 =l alloc8 8 - stored %.3, %.4 -@body.4 - ret -} diff --git a/test/float-promote.c b/test/float-promote.c index 572719a..22e9fa7 100644 --- a/test/float-promote.c +++ b/test/float-promote.c @@ -1,8 +1,6 @@ -void g1(); -void g2(int, ...); -void g3(float); +void g1(int, ...); +void g2(float); void f(void) { - g1(1.0f); - g2(0, 1.0f); - g3(1.0f); + g1(0, 1.0f); + g2(1.0f); } diff --git a/test/float-promote.qbe b/test/float-promote.qbe index 97638e7..069b939 100644 --- a/test/float-promote.qbe +++ b/test/float-promote.qbe @@ -3,9 +3,7 @@ function $f() { @start.1 @body.2 %.1 =d exts s_1 - call $g1(d %.1) - %.2 =d exts s_1 - call $g2(w 0, ..., d %.2) - call $g3(s s_1) + call $g1(w 0, ..., d %.1) + call $g2(s s_1) ret } diff --git a/test/kr-function-argument-promotion.c b/test/kr-function-argument-promotion.c deleted file mode 100644 index 7592da1..0000000 --- a/test/kr-function-argument-promotion.c +++ /dev/null @@ -1,10 +0,0 @@ -int f(c) - unsigned char c; -{ - return c; -} - -int main(void) -{ - return f(0x100); -} diff --git a/test/kr-function-argument-promotion.qbe b/test/kr-function-argument-promotion.qbe deleted file mode 100644 index 6d2f2b8..0000000 --- a/test/kr-function-argument-promotion.qbe +++ /dev/null @@ -1,18 +0,0 @@ -export -function w $f(w %.1) { -@start.1 - %.2 =w extub %.1 - %.3 =l alloc4 1 - storeb %.2, %.3 -@body.2 - %.4 =w loadub %.3 - %.5 =w extub %.4 - ret %.5 -} -export -function w $main() { -@start.3 -@body.4 - %.1 =w call $f(w 256) - ret %.1 -} diff --git a/test/lvalue-conversion.c b/test/lvalue-conversion.c index 6bbc326..a9bce10 100644 --- a/test/lvalue-conversion.c +++ b/test/lvalue-conversion.c @@ -1,4 +1,4 @@ -void g(); +void g(int); void f(void) { static const unsigned char c = 0; g(c); @@ -111,7 +111,6 @@ typerank(struct type *t) bool typecompatible(struct type *t1, struct type *t2) { - struct type *tmp; struct decl *p1, *p2; if (t1 == t2) @@ -133,23 +132,10 @@ typecompatible(struct type *t1, struct type *t2) return false; goto derived; case TYPEFUNC: - if (!t1->u.func.isprototype) { - if (!t2->u.func.isprototype) - return true; - tmp = t1, t1 = t2, t2 = tmp; - } if (t1->u.func.isvararg != t2->u.func.isvararg) return false; - if (!t2->u.func.paraminfo) { - for (p1 = t1->u.func.params; p1; p1 = p1->next) { - if (!typecompatible(p1->type, typepromote(p1->type, -1))) - return false; - } - return true; - } for (p1 = t1->u.func.params, p2 = t2->u.func.params; p1 && p2; p1 = p1->next, p2 = p2->next) { - tmp = t2->u.func.isprototype ? p2->type : typepromote(p2->type, -1); - if (!typecompatible(p1->type, tmp)) + if (!typecompatible(p1->type, p2->type)) return false; } if (p1 || p2) |