aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2024-04-14 23:12:21 -0700
committerMichael Forney <mforney@mforney.org>2024-04-15 01:23:59 -0700
commitcc49fbc44550d3927c592445a3e7f89a4481a63a (patch)
tree570910b0eb05abac46fe60fba4fbce304ef15a40
parent7ee038a55d70ffb94139869acf423ebe0dd52b70 (diff)
Remove support for non-prototype function declarations and definitions
These were removed in C23.
-rw-r--r--cc.h2
-rw-r--r--decl.c89
-rw-r--r--expr.c6
-rw-r--r--qbe.c6
-rw-r--r--test/compatible-function-types.c30
-rw-r--r--test/compatible-function-types.qbe16
-rw-r--r--test/float-promote.c10
-rw-r--r--test/float-promote.qbe6
-rw-r--r--test/kr-function-argument-promotion.c10
-rw-r--r--test/kr-function-argument-promotion.qbe18
-rw-r--r--test/lvalue-conversion.c2
-rw-r--r--type.c16
12 files changed, 42 insertions, 169 deletions
diff --git a/cc.h b/cc.h
index 5e244f0..fffee6f 100644
--- a/cc.h
+++ b/cc.h
@@ -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;
diff --git a/decl.c b/decl.c
index 40ae579..57c4a4d 100644
--- a/decl.c
+++ b/decl.c
@@ -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) {
diff --git a/expr.c b/expr.c
index 0e7c0b4..22fd242 100644
--- a/expr.c
+++ b/expr.c
@@ -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();
diff --git a/qbe.c b/qbe.c
index e425e58..f3f50b3 100644
--- a/qbe.c
+++ b/qbe.c
@@ -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);
diff --git a/type.c b/type.c
index d8c1a6a..671914f 100644
--- a/type.c
+++ b/type.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)